我正在用tkinter创建一个程序,它带有一个存储在文本文件中的默认名称和密码 . 登录后,您需要打开 Toplevel
窗口并输入要在后续登录中使用的名称和密码 . 我已经定义了我的变量,但如果我想覆盖文本文件,我收到以下内容:
错误“NameError:名称'e1'未定义”
我知道我已经定义了 .
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()
1 回答
所以你有几个选择,但一般来说你有两个主要问题 .
第一个问题是在创建
e1
和e2
输入字段后使用.pack()
. 这是get()
方法的问题,因为如果以这种方式打包,几何管理器将返回None
. 正确的方法是首先使用e1 = Entry(ch, width=20)
创建窗口小部件,然后使用e1.pack()
将其打包到下一行,这将允许get()
在e1
上工作 .第二个问题是局部变量与全局变量的关系 . 你已经在函数
change_login()
中创建了e1
和e2
而没有告诉pythone1
和e2
是全局变量,它会自动假设你想要它们作为局部变量 . 这意味着只能从创建它们的函数中访问变量 .你有几个选择,我会为你解决它们 .
1)快速和脏选项是将
e1
和e2
指定为全局变量 . 这可以通过使用global var_name, var2_name, and_so_on
来完成,因此在这种情况下,将此行添加到change_login():
和save_changes()
函数的顶部:这告诉python将
e1
和e2
添加到全局名称空间,它将允许save_changes()
使用全局名称空间中的变量 .2)另一种方法是使用button命令将2个变量传递给
save_changes()
. 我们需要使用lambda
,我们可以通过添加:到
change_login()
中创建的按钮,并将2个参数添加到save_changes()
,如下所示:这将与第一个选项一样有效,并且它也避免使用全局变量 .
3)第三种选择是将整个程序创建为类,并使用类属性允许变量与类中的所有方法一起使用 .
下面是使用第一个选项的代码示例:
下面是使用第二个选项的代码示例:
下面是您的代码转换为类并使用类属性以避免使用全局变量的示例 .