Python 3.x Tkinter-通过另一个函数更改标签文本

Python 3.x Tkinter-通过另一个函数更改标签文本,python-3.x,tkinter,Python 3.x,Tkinter,我知道经常使用面向对象编程(OOP)编写Tkinter GUI代码,但我尝试保持简单,因为我对Python不熟悉 我编写了以下代码来创建一个简单的GUI: #!/usr/bin/python3 from tkinter import * from tkinter import ttk def ChangeLabelText(): MyLabel.config(text = 'You pressed the button!') def main(): Root = Tk()

我知道经常使用面向对象编程(OOP)编写Tkinter GUI代码,但我尝试保持简单,因为我对Python不熟悉

我编写了以下代码来创建一个简单的GUI:

#!/usr/bin/python3
from tkinter import *
from tkinter import ttk

def ChangeLabelText():
    MyLabel.config(text = 'You pressed the button!')

def main():
    Root = Tk()
    MyLabel = ttk.Label(Root, text = 'The button has not been pressed.')
    MyLabel.pack()
    MyButton = ttk.Button(Root, text = 'Press Me', command = ChangeLabelText)
    MyButton.pack()
    Root.mainloop()

if __name__ == "__main__": main()

我原以为单击按钮时GUI(MyLabel)中的文本会变为“You pressed the button!”,但单击按钮时出现以下错误:

Exception in Tkinter callback
Traceback (most recent call last):
  File "C:\Users\elsey\AppData\Local\Programs\Python\Python35-32\lib\tkinter\__init__.py", line 1549, in __call__
    return self.func(*args)
  File "C:/Users/elsey/Documents/question code.py", line 6, in ChangeLabelText
    MyLabel.config(text = 'You pressed the button!')
NameError: name 'MyLabel' is not defined

我做错了什么?任何指导都将不胜感激。

MyLabel
main()
的本地版本,因此您无法通过
ChangeLabelText()
以这种方式访问它

如果不想更改程序的设计,则需要更改
ChangeLabelText()
的定义,如下所示:

def ChangeLabelText(m):
    m.config(text = 'You pressed the button!')
使用main()时,需要将
MyLabel
作为参数传递给
ChangeLabelText()

但是,如果在声明和定义
MyButton
时编写此
command=ChangeLabelText(MyLabel)
代码,您将再次遇到问题,因为程序将在开始时直接执行
ChangeLabelText()
的主体,并且不会得到所需的结果

要解决后面的问题,您必须使用(并且可能会阅读到)

完整程序 因此,您的程序变成:

#!/usr/bin/python3
from tkinter import *
from tkinter import ttk

def ChangeLabelText(m):
    m.config(text = 'You pressed the button!')

def main():
    Root = Tk()
    MyLabel = ttk.Label(Root, text = 'The button has not been pressed.')
    MyLabel.pack()
    MyButton = ttk.Button(Root, text = 'Press Me', command = lambda: ChangeLabelText(MyLabel))
    MyButton.pack()
    Root.mainloop()

if __name__ == "__main__": 
  main()
演示 单击之前:

点击后:

但是我尽量保持简单,因为我是Python新手,希望这有助于理解类是最简单的方法,否则您必须跳转并手动跟踪许多变量。此外,《Python风格指南》还建议将CamelCase用于类名,并将小写的_加下划线用于变量和函数


您确定不想将其作为一个类来执行吗(我认为随着项目的发展,代码会变得更干净一些)?以下是一种实现您所寻找目标的方法:

#!/usr/bin/python3
from tkinter import *
from tkinter import ttk


class myWindow:
    def __init__(self, master):
        self.MyLabel = ttk.Label(root, text = 'The button has not been pressed.')
        self.MyLabel.pack()
        self.MyButton = ttk.Button(root, text = 'Press Me', command = self.ChangeLabelText)
        self.MyButton.pack()

    def ChangeLabelText(self, event=None):
        self.MyLabel.config(text = 'You pressed the button!')


if __name__ == "__main__": 
    root = Tk()
    mainWindow = myWindow(root)
    root.mainloop()
在Mac电脑中,在按下按钮之前是这样的:

Exception in Tkinter callback
Traceback (most recent call last):
  File "C:\Users\elsey\AppData\Local\Programs\Python\Python35-32\lib\tkinter\__init__.py", line 1549, in __call__
    return self.func(*args)
  File "C:/Users/elsey/Documents/question code.py", line 6, in ChangeLabelText
    MyLabel.config(text = 'You pressed the button!')
NameError: name 'MyLabel' is not defined

当你按下它时:


但基本上,为了能够更改标签或按钮中的文本,您需要确保它具有活动引用。在本例中,我们通过将窗口创建为一个类并引用表单
self中的小部件来实现。widget_name=widget()

您需要一个对象引用才能访问MyLabel最简单的解决方案是将
全局MyLabel
添加到这两个函数中。但对于多个小部件来说,这很快就会变得一团糟。在某种程度上,一个或多个以小部件作为属性、以命令作为方法的类将获胜。感谢您的解决方案。我会将此标记为最佳答案,但我想我会尝试在代码中使用类。我认为如果不使用通配符导入,此答案会稍微好一点。是的,你说得很对。你最近也通过你对另一位成员的评论提到了这一点。我也会使用类,但OP说他是一个初学者,所以介绍他lambda和如何使用带参数的回调方法,我认为,对于初学者来说已经太多了,现在提到他PEPs可能还为时过早。正如人们常说的,大量的信息扼杀了信息。但是如果你阅读下面的内容,我对其中一个答案进行了评论,以鼓励OP使用OOP,我对下面的两个答案都投了赞成票。但是你还是对的@bryanoakley谢谢你的回答,谢谢你让我注意到你的风格指南。是的,开始学习这个好答案中所示的面向对象概念是很好的。谢谢你的回答。我感谢你的帮助。