如何使用 tkinter 中的按钮更改没有全局关键字的全局变量?

发布于 2025-01-11 15:23:48 字数 415 浏览 0 评论 0原文

我正在制作一个石头剪刀布程序,当他们单击按钮时,我需要更改轮到谁,但我不想使用 global 关键字,因为该程序位于函数内部。

以下是我在不使用 global 关键字的情况下尝试执行的操作的示例:

from tkinter import *
root = Tk()

var = 1

def buttonClick():
    global var
    var += 1
    print(var)

button = Button(root, text="button", command=buttonClick).pack()
root.mainloop()

我尝试编写 command=(var += 1) 但这不起作用。

I am making a rock paper scissors program and I need to change whose turn it is when they click a button, but I do not want to use the global keyword because the program is inside of a function.

Here is an example of what I am trying to do without using the global keyword:

from tkinter import *
root = Tk()

var = 1

def buttonClick():
    global var
    var += 1
    print(var)

button = Button(root, text="button", command=buttonClick).pack()
root.mainloop()

I have tried to write command=(var += 1) but that did not work.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

傾旎 2025-01-18 15:23:48

如果整个脚本位于函数内部(包括 buttonClick() 函数),则使用 nonlocal 关键字:

def buttonClick():
    nonlocal var
    var += 1
    print(var)

如果函数未嵌套,唯一的方法是创建一个全局变量和两个函数中的global关键字。

If the whole script is inside a function (including the buttonClick() function) then use the nonlocal keyword:

def buttonClick():
    nonlocal var
    var += 1
    print(var)

If the function is not nested, the only way is to create a global variable and the global keyword in both functions.

你的笑 2025-01-18 15:23:48

不,你确实不能。例如,如果全局 var 是一个列表,则可以更改它的内容。然后您可以将命令编写为没有完整函数体的 lambda 表达式。

但这根本不是最好的设计。

Tkinter 事件模型与 Python 对象模型很好地结合在一起 - 在某种程度上,您可以将与 UI 相关的所有内容包含在一个类中,而不是仅仅将 UI 组件放在顶层(全局的所有内容),通过稀疏函数进行协调 - 即使它曾经有过只是一个例子 - 这样你的程序就可以将 var 作为“self.var”访问,将命令作为“self.button_click”访问,如果不应该的话,几乎不会出现混乱的危险。

只是您找到的大多数文档和教程都会有继承 tkinter 对象本身并将元素添加到现有类之上的 OOP 示例。我强烈反对这种方法:tkinter 类足够复杂,有数百个方法和属性 - 即使是一个复杂的程序也只需要几十个内部状态让您担心。

最好的事情是关联:你想要访问的所有东西都应该是你班级的成员。在程序开始时,您实例化您的类,这将创建 UI 元素并保留对它们的引用:

import tkinter as tk # avoid wildcard imports: it is hard to track what is available on the global namespace

class App:
    def __init__(self):
        self.root = tk.Tk()
        self.var = 1
        # keep a refernce to the button (not actually needed, but you might)
        self.button = tk.Button(self.root, text="button", command=self.buttonClick)
        self.button.pack()

    def buttonClick(self):
        # the button command is bound to a class instance, so
        # we get "self" as the object which has the "var" we want to change
        self.var += 1
        print(self.var)

    def run(self):
        self.root.mainloop()


if __name__ == "__main__": # <- guard condition which allows claases and functions defined here to be imported by larger programs
    app = App()
    app.run()

No, you indeed can't. It would be possible to change the contents of a global varif it were a list, for example. And then you could write your command as a lambda expression with no full function body.

But this is not the best design at all.

Tkinter event model couples nicely with Python object model - in a way that instead of just dropping your UI components at the toplevel (everything global), coordinated by sparse functions, you can contain everything UI related in a class - even if it will ever have just one instance - that way your program can access the var as "self.var" and the command as "self.button_click" with little danger of things messing up were they should not.

It is just that most documentation and tutorial you find out will have OOP examples of inheriting tkinter objects themselves, and adding your elements on top of the existing classes. I am strongly opposed to that approach: tkinter classes are complex enough, with hundreds of methods and attributes -wereas even a sophisticated program will only need a few dozens of internal states for you to worry about.

Best thing is association: everything you will ever care to access should eb a member of your class. In the start of your program, you instantiate your class, that will create the UI elements and keep references to them:

import tkinter as tk # avoid wildcard imports: it is hard to track what is available on the global namespace

class App:
    def __init__(self):
        self.root = tk.Tk()
        self.var = 1
        # keep a refernce to the button (not actually needed, but you might)
        self.button = tk.Button(self.root, text="button", command=self.buttonClick)
        self.button.pack()

    def buttonClick(self):
        # the button command is bound to a class instance, so
        # we get "self" as the object which has the "var" we want to change
        self.var += 1
        print(self.var)

    def run(self):
        self.root.mainloop()


if __name__ == "__main__": # <- guard condition which allows claases and functions defined here to be imported by larger programs
    app = App()
    app.run()

抹茶夏天i‖ 2025-01-18 15:23:48

是的,你可以。这是一种很奇怪的方法,它说明了它可以完成,尽管它肯定不是推荐的执行此类操作的方法。 免责声明:我的想法来自于相关问题

from tkinter import *

root = Tk()
var = 1
button = Button(root, text="button",
                command=lambda: (globals().update(var=var+1), print(var)))
button.pack()
root.mainloop()

Yes, you can. Here's a hacky way of doing it that illustrates that it can be done, although it's certainly not a recommended way of doing such things. Disclaimer: I got the idea from an answer to a related question.

from tkinter import *

root = Tk()
var = 1
button = Button(root, text="button",
                command=lambda: (globals().update(var=var+1), print(var)))
button.pack()
root.mainloop()
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文