不同类中的Python 3 tkinter按钮命令

Posted

技术标签:

【中文标题】不同类中的Python 3 tkinter按钮命令【英文标题】:Python 3 tkinter button command inside different class 【发布时间】:2015-08-21 19:27:49 【问题描述】:

我正在创建一个 Python (3.4.3) - tkinter 程序,我想知道是否可以从另一个 class 内部引用 def (self.get_details) 来获取按钮的命令。我无法在任何地方找到这个问题的答案,所以我想我只是问问。

例子:

import tkinter as tk
...

class Widgets(tk.Frame):
    def __init__(self, parent):
        tk.Frame.__init___(self, parent)
        self.parent = parent

        self.initUI()

    def initUI():

        # Lots of other different tkinter widgets go here

        self.button = tk.Button(command=App(get_details))
        self.button.pack()


class PopUp(tk.TopLevel): ....

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

        self.initUI()

    def get_details(self):

        # Complete a function

    def initUI(self):

        self.parent.title("My Application")
        self.style = Style()
        self.style.theme_use("default")

        self.pack()

        self.widgets = Widgets(self)
        self.widgets.pack(side="top", anchor="center", fill="both", expand=True)

if __name__ == "__main__":

    root = tk.Tk()
    App(root).pack(side="top", fill="both", expand=True)
    root.resizable(0,0)
    root.mainloop()

所以我想要一个属于Widgets() 类的按钮来调用属于App() 类的def get_details(self) 命令,其中包含Widgets() 类。

我希望我的描述性足够,这个问题很难用词来形容。总的来说,我对 Python 还是有点陌生​​。谢谢!

编辑:

按照建议,我将其更改为self.parent.get_details(),这很有效!但是,当我从 def get_details() 中的 Widgets() 类引用 tkinter 小部件时,例如:self.button,我得到:

AttributeError: 'App' object has no attribute 'button'

所以我尝试将按钮引用为:self.parent.button,我收到了:

AttributeError: 'tkapp' object has no attribute 'button'

我应该如何调用/引用按钮?谢谢!

【问题讨论】:

self.parent.get_details() 应该可以工作。你试过吗? 主要工作,见编辑。 要在get_details 中引用Widgets 对象中的某些内容,请使用self.widgets.button。无论您在哪个对象中,self 指的是该对象的一个​​实例。 【参考方案1】:

App 中,您创建一个Widgets 对象并保存对它的引用,名为self.widgets。执行此操作时,会将对该 App 对象的引用传递给 Widgets 对象。 App 实例引用作为self.parent 保存在Widgets 对象中。请记住,self 的这两种用法指的是不同的对象:而在App 中,self 指的是该App 对象的当前实例。在Widgets 中,self 指的是该Widgets 对象的当前实例。要引用其他类中的内容,您必须使用正确的引用并遵循路径。

App 实例中:

self             this App instance
.widgets         the Widgets instance it contains
.button          the button in that Widget instance

Widgets 实例中:

self             this Widgets instance
.parent          the App object that created this Widgets object
.get_details     the get_details function in the parent App object

在下文中,我修复了代码的剩余位(... 导致语法错误,Style 未定义等),并提供了一个小示例,说明如何从另一个对象引用每个对象。该按钮最初显示“你好”,您可以通过单击将其更改为“再见”。

import tkinter as tk

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

        self.initUI()

    def initUI(self):

        # Lots of other different tkinter widgets go here

        self.button = tk.Button(text='hello', command=self.parent.get_details)
        self.button.pack()

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

        self.initUI()

    def get_details(self):

        self.widgets.button.config(text='goodbye')

    def initUI(self):

        self.parent.title("My Application")

        self.pack()

        self.widgets = Widgets(self)
        self.widgets.pack(side="top", anchor="center", fill="both", expand=True)

if __name__ == "__main__":

    root = tk.Tk()
    App(root).pack(side="top", fill="both", expand=True)
    root.resizable(0,0)
    root.mainloop()

【讨论】:

感谢您向我解释得如此清楚。这是一个真正的帮助!我尝试将按钮设置为self.widgets.button,但它仍然再次给了我“应用程序”的属性错误。然后,我在尝试调用该对象的正上方重新定义了self.widgets = Widgets(self),但这给了我一个RuntimeError: maximum recursion depth exceeded while calling a Python object。很抱歉这么痛苦! @jimimatthews,我添加了您的代码的修改版本来演示如何引用各种对象。 你帮了大忙,非常感谢你的耐心,你是个传奇!

以上是关于不同类中的Python 3 tkinter按钮命令的主要内容,如果未能解决你的问题,请参考以下文章

如何在没有按钮的情况下关闭tkinter窗口而不完全关闭Python?

Tkinter GUI 中的多线程,不同类中的线程

如何使用 Python 3.8 中的按钮读取 Tkinter 中的条目

在 tkinter 中,在 python 3 中,我怎样才能让一个按钮执行一个命令来执行诸如“def helloCallBack(a)”之类的功能,并允许我给出一个? [复制]

Python中带有lambda的tkinter按钮命令

在 Python 3 中使用 tkinter 更改单选按钮的背景颜色