2017-09-14 89 views
-1

我正在用tkinter創建一個程序,它帶有一個存儲在文本文件中的默認名稱和密碼。登錄後,您需要打開Toplevel窗口,然後輸入您要在後續登錄中使用的名稱和密碼。我定義我的變量,但如果我要覆蓋文本文件我收到如下:如何覆蓋tkinter中的文本文件中的數據

Error "NameError: name 'e1' is not defined"

我知道我已經定義。

import sys 
from tkinter import messagebox 
from tkinter import * 


now = open("pass.txt","w+") 
now.write("user\n") 
now.write("python3") 
now.close() 


def login_in(): 
    with open("pass.txt") as f: 
     new = f.readlines() 
     name = new[0].rstrip() 
     password = new[1].rstrip() 
    if entry1.get() == name and entry2.get() == password: 
     root.deiconify() 
     log.destroy() 
    else: 
     messagebox.showerror("error","login Failed") 


def change_login(): 
    ch = Toplevel(root) 
    ch.geometry('300x300') 
    e1 = Entry(ch, width=20).pack() 
    e2 = Entry(ch, width=20).pack() 
    sb = Button(ch, text="save", command=save_changes).pack() 

def save_changes(): # function to change data in the txt file 
    data = e1.get() + "\n " + e2.get() 
    with open("pass.txt", "w") as f: 
     f.writelines(data) 


root= Tk() 
log = Toplevel() 


root.geometry("350x350") 
log.geometry("200x200") 

entry1 = Entry(log) 
entry2 = Entry(log) 
button1 = Button(log, text="Login", command=login_in) #Login button 

entry1.pack() 
entry2.pack() 
button1.pack() 

label = Label(root, text="welcome").pack() 
butt = Button(root, text="change data in file", command=change_login).pack() 

root.withdraw() 
root.mainloop()  
+2

'e1'是一個變量,它是'change_login()'的局部變量,但是你在'save_changes()'中調用它,它不存在。所以它會拋出這個錯誤,告訴你該變量不存在於本地空間中。 –

回答

0

所以你在這裏有幾個選擇,但總的來說你有兩個主要問題。

第一個問題是在創建e1e2輸入字段後使用.pack()。這是get()方法的一個問題,因爲如果按此方式打包,幾何體管理器將返回None。正確的方法是首先用e1 = Entry(ch, width=20)創建窗口小部件,然後用e1.pack()將它打包在下一行,這將允許get()e1上工作。

第二個問題是局部變量與全局變量的問題。您已經在函數change_login()內創建了e1e2,並且不告訴python e1e2是全局變量,它會自動假定您希望它們作爲局部變量。這意味着變量只能在創建它們的函數內訪問。

您有幾個選項,我會爲您分解它們。

1)快速和骯髒的選項是將e1e2作爲全局變量。這可以通過在這種情況下使用global var_name, var2_name, and_so_on所以做這一行添加到您的change_login():save_changes()功能上:

global e1, e2 

這也告訴Python添加e1e2到全局命名空間,它將使save_changes()使用全局名稱空間中的變量。

2)另一種方法是使用button命令將2個變量傳遞給save_changes()。我們將需要使用lambda對於這一點,我們可以通過添加做到這一點:

command = lambda e1=e1, e2=e2: save_changes(e1, e2) 

change_login()創建的按鈕並添加2個參數save_changes()這樣的:

save_changes(e1, e2) 

這只是工作以及第一個選項,它也避免使用全局變量。

3)第三種選擇是將整個程序創建爲一個類,並使用類屬性允許變量與類中的所有方法一起工作。

以下是使用第一個選項代碼的例子:

import sys 
from tkinter import messagebox 
from tkinter import * 

now = open("pass.txt","w+") 
now.write("user\n") 
now.write("python3") 
now.close() 

def login_in(): 
    with open("pass.txt") as f: 
     new = f.readlines() 
     name = new[0].rstrip() 
     password = new[1].rstrip() 
    if entry1.get() == name and entry2.get() == password: 
     root.deiconify() 
     log.destroy() 
    else: 
     messagebox.showerror("error","login Failed") 

def change_login(): 
    global e1, e2 
    ch = Toplevel(root) 
    ch.geometry('300x300') 
    e1 = Entry(ch, width=20) 
    e1.pack() 
    e2 = Entry(ch, width=20) 
    e2.pack() 
    sb = Button(ch, text="save", command=save_changes).pack() 

def save_changes(): # function to change data in the txt file 
    global e1, e2 
    data = e1.get() + "\n" + e2.get() # removed space after \n 
    with open("pass.txt", "w") as f: 
     f.writelines(data) 

root= Tk() 
log = Toplevel() 
root.geometry("350x350") 
log.geometry("200x200") 

entry1 = Entry(log) 
entry2 = Entry(log) 
button1 = Button(log, text="Login", command=login_in) #Login button 

entry1.pack() 
entry2.pack() 
button1.pack() 

label = Label(root, text="welcome").pack() 
butt = Button(root, text="change data in file", command=change_login).pack() 

root.withdraw() 
root.mainloop() 

下面是使用第二個選項的代碼示例:

import sys 
from tkinter import messagebox 
from tkinter import * 

now = open("pass.txt","w+") 
now.write("user\n") 
now.write("python3") 
now.close() 

def login_in(): 
    with open("pass.txt") as f: 
     new = f.readlines() 
     name = new[0].rstrip() 
     password = new[1].rstrip() 
    if entry1.get() == name and entry2.get() == password: 
     root.deiconify() 
     log.destroy() 
    else: 
     messagebox.showerror("error","login Failed") 

def change_login(): 
    ch = Toplevel(root) 
    ch.geometry('300x300') 
    e1 = Entry(ch, width=20) 
    e1.pack() 
    e2 = Entry(ch, width=20) 
    e2.pack() 
    Button(ch, text="save", command=lambda e1=e1, e2=e2: save_changes(e1, e2)).pack() 

def save_changes(e1, e2): # function to change data in the txt file 
    data = e1.get() + "\n" + e2.get() # removed space after \n 
    with open("pass.txt", "w") as f: 
     f.writelines(data) 

root= Tk() 
log = Toplevel() 
root.geometry("350x350") 
log.geometry("200x200") 

entry1 = Entry(log) 
entry2 = Entry(log) 
button1 = Button(log, text="Login", command=login_in) #Login button 

entry1.pack() 
entry2.pack() 
button1.pack() 

label = Label(root, text="welcome").pack() 
butt = Button(root, text="change data in file", command=change_login).pack() 

root.withdraw() 
root.mainloop() 

下面是轉換代碼示例到一個類並使用類屬性來避免使用全局變量。

import sys 
from tkinter import messagebox 
from tkinter import * 


class MyApp(Frame): 

    def __init__(self, master, *args, **kwargs): 
     Frame.__init__(self, master, *args, **kwargs) 

     self.master = master 
     self.master.withdraw() 

     self.log = Toplevel() 
     self.master.geometry("350x350") 
     self.log.geometry("200x200") 

     self.entry1 = Entry(self.log) 
     self.entry2 = Entry(self.log) 
     self.button1 = Button(self.log, text="Login", command=self.login_in) 

     self.entry1.pack() 
     self.entry2.pack() 
     self.button1.pack() 

     Label(root, text="welcome").pack() 
     Button(root, text="change data in file", command=self.change_login).pack() 

    def login_in(self): 
     with open("pass.txt") as f: 
      new = f.readlines() 
      name = new[0].rstrip() 
      password = new[1].rstrip() 
     if self.entry1.get() == name and self.entry2.get() == password: 
      self.master.deiconify() 
      self.log.destroy() 
     else: 
      messagebox.showerror("error","login Failed") 

    def change_login(self): 
     ch = Toplevel(self.master) 
     ch.geometry('300x300') 
     self.e1 = Entry(ch, width=20) 
     self.e1.pack() 
     self.e2 = Entry(ch, width=20) 
     self.e2.pack() 
     Button(ch, text="save", command=self.save_changes).pack() 

    def save_changes(self): 
     data = "{}\n{}".format(self.e1.get(), self.e2.get()) 
     with open("pass.txt", "w") as f: 
      f.writelines(data) 


if __name__ == "__main__": 
    now = open("pass.txt","w+") 
    now.write("user\n") 
    now.write("python3") 
    now.close() 

    root = Tk() 
    app = MyApp(root) 
    root.mainloop() 
+0

感謝@雪山科技的更正,我意識到我的變量不是全球性的@ @伊森領域指出,所以我正在解決它,直到你發佈你的答案。一切正常。再次感謝。 –

+0

這是一個問題,但是你也有一個'pack()'的問題,即使你把e11和e2設置爲全局變量,也會導致程序失敗。這說快樂的編碼! –

+0

在輸入字段中鍵入的新數據真正覆蓋舊的,但是當我再次運行程序並在登錄階段鍵入新數據時,我無法登錄,直到我使用文件中的舊數據:「user」和「python3」。我怎樣才能讓它只接受在登錄階段輸入到文本文件中的新數據,而忽略我創建時寫入文件的最初數據。 –