按下按钮时刷新 tkinter 框架

新手上路,请多包涵

我正在使用 tkinter 中两个框架之间切换 的代码来制作我的 GUI。我有一个带有刷新和重启按钮的框架。

我最初的想法是让重启按钮转到开始页面,如下面的代码所示,但如果再次调用此框架,它仍然会显示上一次尝试的条目。

我已经为刷新按钮尝试了 .destroy() 但是当我再次调用 PLG 框架时我收到了一条回溯消息。

对于重启按钮,我将如何关闭 PLG 框架,转到开始页面,然后再次选择 PLG?

对于刷新按钮,我将如何删除条目小部件中的条目和文本拖欠,以便可以进行另一个条目并返回新的答案?

 class PLG(tk.Frame):
    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        self.controller = controller
        label = tk.Label(self, text="Enter the engine size (cc) below", font=controller.title_font)
        label.pack(side="top", fill="x", pady=10)
        vcmd = (self.register(self.onValidate), '%S')
        self.weight_entry = tk.Entry(self, validate='key', vcmd = vcmd)
        self.weight_entry.pack(pady = 10)
        tk.Button(self, text='Click here to display price', command=self.show_option).pack()
        self.text = tk.Text(self)
        self.text.pack(pady = 10)
        self.text.config(state='disabled')
        restart_button = tk.Button(self, text="Restart",
              command=self.restart)
        restart_button.pack()
        refresh_button = tk.Button(self, text="Refresh", command=self.refresh).pack()
        refresh_button.pack()

    def onValidate(self,S):
    if S in ['0','1','2', '3', '4', '5', '6', '7', '8', '9']:
        return True
    else:
        self.bell() # adds a sound effect to error
        self.text.delete(1.0, tk.END) # deletes the error message if valid entry provided
        self.text.insert(tk.END, "Invalid entry.  Please try again.") # displays an error message if a number not provided in entry widget
        return False

    def restart(self):
        self.refresh()
        show_frame("StartPage")

    def refresh(self):
        self.text.config(state='normal')
        self.weight_entry.delete(0,tk.END)
        self.text.delete("1.0", "end")

对这两个要素的建议将不胜感激。

原文由 bagpuss 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 997
2 个回答

第一步是让您的按钮调用适当的函数,而不是使用 lambda 。除非您了解为什么以及何时使用 lambda ,否则它通常只会使代码更难编写和理解。

一旦你让它调用一个函数,你就可以使用该函数来清除条目。

例子:

 class PLG(tk.Frame):
    def __init__(self, parent, controller):
        ...
        tk.Button(self, text="Restart", command=self.restart)
        tk.Button(self, text="Refresh", command=self.refresh)
        ...

    def restart(self):
        self.refresh()
        self.controller.show_frame("StartPage")

    def refresh(self):
        self.weight_entry.delete(0, "end")
        self.text.delete("1.0", "end")

原文由 Bryan Oakley 发布,翻译遵循 CC BY-SA 3.0 许可协议

OP 的问题是关于清除输入字段,因此当您希望看到新输入的空字段时,先前的输入不在页面中。我发布了完成的代码,同时省略了与他的问题无关的 OP 原始代码的功能,因此可以很容易地在其完整上下文中看到解决方案。我一直在寻求使用 Bryan Oakley 关于此主题的著名教程中的相同帧切换代码来解决此问题。我还包含了一个使用 grid_remove 而不是 tkraise 的替代版本,因为这是我解决了当用户尝试在页面中切换时尝试参与焦点遍历的永远活跃但看不见的框架的问题。它还使所有框架都试图保持相同的大小。

 import tkinter as tk

class SampleApp(tk.Tk):

    def __init__(self, *args, **kwargs):
        tk.Tk.__init__(self, *args, **kwargs)

        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 = {}

        # alternate ways to create the frames & append to frames dict: comment out one or the other

        for F in (StartPage, PLG):
            page_name = F.__name__
            frame = F(parent=container, controller=self)
            self.frames[page_name] = frame
            frame.grid(row=0, column=0, sticky="nsew")

        # self.frames["StartPage"] = StartPage(parent=container, controller=self)
        # self.frames["PLG"] = PLG(parent=container, controller=self)
        # self.frames["StartPage"].grid(row=0, column=0, sticky="nsew")
        # self.frames["PLG"].grid(row=0, column=0, sticky="nsew")

        self.show_frame("StartPage")

    # alternate version of show_frame: comment out one or the other

    def show_frame(self, page_name):
        for frame in self.frames.values():
            frame.grid_remove()
        frame = self.frames[page_name]
        frame.grid()

    # def show_frame(self, page_name):
        # frame = self.frames[page_name]
        # frame.tkraise()

class StartPage(tk.Frame):

    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        self.controller = controller

        label = tk.Label(self, text="start page")
        label.pack(side="top", fill="x", pady=10)

        button1 = tk.Button(self, text="Go to Page One", command=lambda: controller.show_frame("PLG"))
        button1.pack()

        button2 = tk.Button(self, text="focus traversal demo only")
        button2.pack()
        button2.focus_set()

        button3 = tk.Button(self, text="another dummy button")
        button3.pack()

        lbl = tk.Label(self, text="tkraise messes up focus traversal\nwhich you can see by testing the two versions of show_frame.()\nUsing grid_remove instead of tkraise solves that,\nwhile preventing frames from being unable to resize to fit their own contents.")
        lbl.pack()

class PLG(tk.Frame):
    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        self.controller = controller
        label = tk.Label(self, text="Enter something below; the two buttons clear what you type.")
        label.pack(side="top", fill="x", pady=10)
        self.wentry = tk.Entry(self)
        self.wentry.pack(pady = 10)
        self.text = tk.Text(self)
        self.text.pack(pady = 10)
        restart_button = tk.Button(self, text="Restart", command=self.restart)
        restart_button.pack()
        refresh_button = tk.Button(self, text="Refresh", command=self.refresh)
        refresh_button.pack()

    def restart(self):
        self.refresh()
        self.controller.show_frame("StartPage")

    def refresh(self):
        self.wentry.delete(0, "end")
        self.text.delete("1.0", "end")
        # set focus to any widget except a Text widget so focus doesn't get stuck in a Text widget when page hides
        self.wentry.focus_set()

if __name__ == "__main__":
    app = SampleApp()
    app.mainloop()

原文由 Luther 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进