首页 文章

如何在tkinter中覆盖文本文件中的数据

提问于
浏览
0

我正在用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 回答

  • 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()
    

相关问题