繁体   English   中英

如何重新初始化 tkinter 中的帧?

[英]How do I reinitialize a frame in tkinter?

我有一个程序,它处理很多从文件中的数据创建对象的问题,并且能够编辑对象,然后将它们保存在同一个文件中。 我正在实现一个 GUI,我正在使用 tkinter 来完成它。 我面临的问题是当我在帧之间来回跳转时帧不更新的问题,因为构造函数方法只在程序开始时运行一次,这是我在屏幕上生成大部分小部件的地方。 以下是我想要完成的示例:

import tkinter as tk

class App(tk.Tk):

    def __init__(self):

        tk.Tk.__init__(self)

        container = tk.Frame(self)
        container.pack(side = "top", fill = "both", expand = True)
        container.grid_rowconfigure(0, weight = 1)
        container.grid_columnconfigure(0, weight = 1)

        self.frames = {}

        for F in (Homescreen, Menuscreen):

            frame = F(container, self)
            self.frames[F] = frame
            frame.grid(row = 0, column = 0, sticky = "nsew")

        self.show_frame(Homescreen)

    def show_frame(self, container):

        frame = self.frames[container]
        frame.tkraise()

class Homescreen(tk.Frame):

    def __init__(self, parent, controller):

        tk.Frame.__init__(self, parent)

        with open("test.txt", "r") as f:
            text = f.readline()
        
        tk.Label(self, text = text).pack()
        tk.Button(self, text = "next page", command = lambda: controller.show_frame(Menuscreen)).pack()
        

class Menuscreen(tk.Frame):

    def __init__(self, parent, controller):

        tk.Frame.__init__(self, parent)
        self.controller = controller
        
        self.entry = tk.StringVar()

        tk.Entry(self, textvariable = self.entry).pack()
        tk.Button(self, text = "back to page", command = self.writeToFile).pack()

        
    def writeToFile(self):

        with open("test.txt", "w") as f:
            f.writelines(self.entry.get())
        
        self.controller.show_frame(Homescreen)


app = App()
app.geometry("500x400")
app.mainloop()

如果我有一个只有一个简单单词的Homescreen文件,我会在主屏幕中将其打印在屏幕上。 然后我移动到第二个框架Menuscreen ,在这里我允许用户输入另一个词,然后我将这个词存储在同一个文本文件中。 然后程序将我们带回主Homescreen ,但问题是打印出来的单词仍然是第一个单词,而不是文本文件中更新的单词。

我尝试使用方法.update().destroy() ,在我执行frame.tkraise()之前的一行,但是.update()方法没有做任何事情,当我使用.destroy()方法时,我收到一条错误_tkinter.TclError: bad window path name

您无法更改“打印出来的单词”,因为Homescreen的构造函数只运行一次。 您需要另一种方法来在您举起Frame时更改条目。 更改在下面评论。 只有 4 个。

import tkinter as tk

class App(tk.Tk):
    def __init__(self):
        tk.Tk.__init__(self)

        container = tk.Frame(self)
        container.pack(side="top", fill="both", expand=True)
        container.grid_rowconfigure(0, weight=1)
        container.grid_columnconfigure(0, weight=1)

        self.frames = {}

        for F in (Homescreen, Menuscreen):

            frame = F(container, self)
            self.frames[F] = frame
            frame.grid(row = 0, column = 0, sticky = "nsew")

        self.show_frame(Homescreen)

    def show_frame(self, container):
        frame = self.frames[container]

        #update the label
        if container is Homescreen: frame.update_label()

        frame.tkraise()


class Homescreen(tk.Frame):
    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
            
        #keep a reference to the label so it can be modified
        self.label = tk.Label(self)
        self.label.pack()
        
        tk.Button(self, text = "next page", command = lambda: controller.show_frame(Menuscreen)).pack()
        
        self.update_label()
        
    #update the label
    def update_label(self):
        with open('test.txt', 'r') as f:
            self.label['text'] = f.read()
        
        
class Menuscreen(tk.Frame):
    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        self.controller = controller
        
        self.entry = tk.StringVar()

        tk.Entry(self, textvariable = self.entry).pack()
        tk.Button(self, text = "back to page", command = self.writeToFile).pack()
        
    def writeToFile(self):
        with open('test.txt', 'w') as f:
            f.write(self.entry.get())
           
        #go back to homescreen 
        self.controller.show_frame(Homescreen)


app = App()
app.geometry("500x400")
app.mainloop()

如果你想让你的脚本更容易使用,我在下面重构了它,并留下了评论。


import tkinter as tk

class App(tk.Tk):
    def __init__(self):
        tk.Tk.__init__(self)
        
        #you do not need `container`
        #using root as the master makes it a more natural controller
        #you were using it more like a proxy        

        self.rowconfigure(0, weight=1)
        self.columnconfigure(0, weight=1)

        #you created a convention with your class names of using "screen"
        #use some kind of "screen" for everything that contains or directly relates to them
        self.screens = {}

        #don't "juggle"
        #create a var, and use it
        for screen in (Menuscreen, Homescreen):
            self.screens[screen] = screen(self)
            self.screens[screen].grid(row=0, column=0, sticky="nsew")

    #renamed to reflect that it relates to your screens
    def show_screen(self, screen):
        target = self.screens[screen]
        
        if screen is Homescreen: target.update_label()
        
        target.tkraise()


class Homescreen(tk.Frame):
    #whatever you put in master becomes the `self.master` of this widget
    #ie.. we are keeping the names the same
    def __init__(self, master, **kwargs):
        tk.Frame.__init__(self, master, **kwargs)
            
        self.label = tk.Label(self)
        self.label.pack()
        
        #this line illustrates how the root is the controller
        tk.Button(self, text="next page", command=lambda: master.show_screen(Menuscreen)).pack()
        
        #init the label text
        self.update_label()
        
    def update_label(self):
        with open('test.txt', 'r') as f:
            self.label['text'] = f.read()
        
        
class Menuscreen(tk.Frame):
    def __init__(self, master, **kwargs):
        tk.Frame.__init__(self, master, **kwargs)
        
        self.entry = tk.StringVar()

        tk.Entry(self, textvariable=self.entry).pack()
        tk.Button(self, text="back to page", command=self.writeToFile).pack()
        
    def writeToFile(self):
        with open('test.txt', 'w') as f:
            f.write(self.entry.get())
        
        #illustrates again how the root is the controller        
        self.master.show_screen(Homescreen)


#this is good practice
if __name__ == "__main__":
    app = App()
    app.geometry("500x400")
    app.mainloop()

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM