【问题标题】:Tkinter variable not changing with Checkbutton in functionTkinter 变量不随功能中的 Checkbutton 改变
【发布时间】:2025-12-03 08:05:02
【问题描述】:

由于某种原因,我的 Checkbutton 变量代码在函数内部时不会更改工作,但是,在函数外部和自己的脚本中时它可以工作。这是函数外部的代码

from tkinter import *

basket = ['apple','banana','orange']
win2 = Tk()
buttons = []
variables = []
for fruit in basket:
    variable = BooleanVar()
    checkbutton = Checkbutton(win2, text = fruit,variable = variable).pack()
    variables.append(variable)
    buttons.append(checkbutton)
Button(win2, text='Quit', command=win2.destroy).pack()
Button(win2, text='Peek', command=allstates).pack()
mainloop()

这是在函数内部定义的代码

from tkinter import *
def selectfruit():
    def allstates(): 
        for variable in variables:
            print(variable.get())
    basket = ['apple','banana','orange']
    win2 = Tk()
    print(stls)
    buttons = []
    variables = []
    for fruit in basket:
        variable = BooleanVar()
        checkbutton = Checkbutton(win2, text = fruit,variable = variable).pack(side = TOP)
        variables.append(variable)
        buttons.append(checkbutton)
    Button(win2, text='Quit', command=win2.destroy).pack()
    Button(win2, text='Peek', command=allstates).pack()

对于代码的顶部,当我选中一个框时,变量变为 True。对于最底层的,无论我做什么,他们都停留在 False。

【问题讨论】:

  • win2 = Tk() 令人担忧 - 这是否意味着您在程序的其他地方调用了Tk()?这会导致变量不起作用 - 以及许多其他问题。使用Toplevel() 创建额外的窗口。
  • 在@jasonharper 建议之后,为什么不尝试将variable = BooleanVar() 更改为var1 = BooleanVar() 之类的,参数名称和变量名称相同,可能会引起一些混乱
  • @jasonharper 是的,我一直在这个程序中使用多个窗口。我将它切换到 Toplevel 而不是 Tk() 并且它起作用了。您能解释一下为什么多个窗口会导致程序出现问题吗?我认为这会很好,因为它们是单独的类
  • 调用Tk() 不仅仅是给你一个窗口——它创建了一个完全独立的GUI 环境。在一个环境中创建的变量、图像等根本无法被不同环境中的小部件访问。
  • 我明白了。非常感谢!

标签: python tkinter


【解决方案1】:

为您的 BooleanVar 提供适当的主/父:

variable = BooleanVar(win2)

如果我没记错的话,没有明确设置主/父,
自动使其成为隐式创建的全局根的子节点
(例如在全局范围内编写 root = Tk(),并将其用作父级)。
(在您的情况下,如果您之前在全局范围内创建了 win2,
那么这将被隐式使用 - 请参见下面的示例。)

所以你的代码在你的函数之外工作时,
因为 BooleanVar 和 CheckButton 恰好有相同的 Tk/root。

当您将代码放入函数中时,
BooleanVar 和 CheckButton 获得不同的 Tks/roots。
(BooleanVar 获取(可能是隐式创建的)全局根,
CheckButton 获取您在函数内部创建的新 win2)

编辑/澄清:
但是,是的,使用 Toplevel 可能是正确的选择。
只需注意原始问题是什么;
它可以并且确实可以与多个 Tk 小部件一起使用。


省略父母时自动养育的示例
(直接从交互式解释器复制):

未指定父/主(此处为 Label 小部件),
创建任何 Tk 小部件
==
隐式使用,隐式创建的全局 Tk/root
(这是弹出的窗口,在第一个 'Label()' 之后)
(注意:隐式创建的全局 Tk,会有所不同
来自任何 Tk 小部件,在它之后显式创建)

>>> from tkinter import *
>>> l1 = Label()
>>> l2 = Label()
>>> id(l1.master) == id(l2.master)
True
>>> root = Tk()
>>> id(root) == id(l1.master)
False

未指定父/主(此处为 Label 小部件),
明确创建了 Tk 小部件
==
隐式使用已经存在的 Tk 小部件

>>> from tkinter import *
>>> root = Tk()
>>> l = Label()
>>> id(root) == id(l.master)
True

【讨论】: