如何正确引用 tkinter 中的框架名称

How to reference correctly to frame names in tkinter

我正在 tkinter 中创建纸牌游戏,需要有关引用框架名称的帮助。我的问题是,当我想要 "refresh" 框架时,我需要销毁并重新创建它,这会改变框架的渐进编号。

请看下面的代码。该示例显示第三帧在重新创建时每次都会获得一个新名称。

import tkinter as tk


class RootFrame(tk.Tk):

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        self.main_window = tk.Frame(self)
        self.main_window.pack(side="top", fill="both", expand=True)
        self.main_label = tk.Label(self.main_window, text="Main Window")
        self.main_label.pack()

        self.second_frame = SecondFrame(self.main_window, self)
        self.second_frame.pack()


class SecondFrame(tk.Frame):

    def __init__(self, parent, controller, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.controller = controller

        label = tk.Label(self, text="Second Frame")
        label.pack()

        self.create_third_frame()

    def create_third_frame(self):
        self.third_frame = ThirdFrame(self, self.controller)
        self.third_frame.pack()

    def update_frame(self):
        self.third_frame.destroy()
        self.create_third_frame()


class ThirdFrame(tk.Frame):

    def __init__(self, parent, controller, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.controller = controller
        self.parent = parent

        label = tk.Label(self, text="Third Frame")
        label.pack()

        refresh_button = tk.Button(
            self, text="Resfresh", command=self.parent.update_frame)
        refresh_button.pack()

        print(self.winfo_name())


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

上面的代码是用来说明问题的。请 运行 代码,您将在终端中看到不断变化的小部件名称。

我在实际代码中使用 winfo_parentwinfo_name 来为按钮绑定创建不同的条件。例如,如果用户单击 frame6 中的 widget1 发生 X,当我单击 frame2 中的 widget8 时发生 Y。这一直有效,直到我 destroy() 和重新创建一些东西,一切都坏了。

我想使用 winfo_namewinfo_parent 进行这种引用并不是正确的解决方法,但我真的想不出别的方法了。

我不确定你到底在问什么,但你可以为小部件指定一个特定的名称:

def create_third_frame(self):
    self.third_frame = ThirdFrame(self, self.controller, name='testframe')
    self.third_frame.pack()

那么每次创建的框架名称都会保持一致

您还可以使用 Tk().nametowidget() 按名称引用小部件,请在此处查看此相关答案:Is it possible to search widget by name in Tkinter?

>>> from Tkinter import *
>>> win = Tk()
>>> button = Button( Frame( win, name = "myframe" ), name = "mybutton" )
>>> win.nametowidget("myframe.mybutton")
<Tkinter.Button instance at 0x2550c68>

不过,我建议坚持使用 OOP 方法,只需从您的代码中引用它,例如 self.thirdframes,您可能有 listdictThirdFrame ] 对象。这样,您的 python 代码就可以轻松引用对象,而无需返回到 tcl 解释器并解析小部件名称。如果你永远只有一个 ThirdFrame,那么只要你需要它就可以参考 self.thirdframe