【问题标题】:Checkbuttons aren't working inside function检查按钮在功能内部不起作用
【发布时间】:2020-10-05 21:54:45
【问题描述】:

基本上我有一堆检查按钮,默认情况下有一些打开,一些关闭。我遇到了一个问题,如果我将复选按钮放在函数中,默认情况下它们不会像应有的那样打开。

这是工作代码:

from tkinter import *

root = Tk()

integer = IntVar(value=1)
Checkbutton(root, text="Should be on by default", variable=integer).grid()

root.mainloop()

这是不工作的代码:

from tkinter import *

root = Tk()

def main():
    integer = IntVar(value=1)
    Checkbutton(root, text="Should be on by default", variable=integer).grid()

main()
root.mainloop()

谁能解释一下这是为什么?

【问题讨论】:

  • 在第二个示例中,IntVar 仅由局部变量引用,并在函数结束时消失。如果没有 var,Checkbutton 就无法存储其状态。

标签: python tkinter


【解决方案1】:

当您看到该窗口时,integer 已不存在,并且该复选框显示为未选中,因为缺少用于存储其状态的变量。

比较:

from tkinter import *

root = Tk()


def main():
    global integer
    integer = IntVar(value=1)
    Checkbutton(root, text="Should be on by default", variable=integer).grid()


main()
root.mainloop()

global integer 告诉 Python 这个integer 应该在“全局”级别定义,因此它会保留在函数之后。

顺便说一句,根据变量的类型命名变量是不好的做法 - 尝试选择一个代表其值含义的名称,而不是描述其类型。

您分享了一些具有类似问题的附加代码(仅重复重要的元素):

from tkinter import *


def change_job_skills(name):
    top_window = Toplevel(root)
    # ..
    skill_dictionary = {}
    # ..
    row_ = 2
    column_ = 0
    # ..
    job_focuses_dictionary = {}
    for key in sorted(job_focuses_dictionary.keys()):
        Checkbutton(top_window, text=key.strip(""),
                    variable=job_focuses_dictionary[key]).grid(row=row_, column=column_, sticky=W)
    # ..
    # no definition was provided of actually_change_job_skills, but it's not important here
    Button(top_window, text='Submit',
           command=lambda: [actually_change_job_skills(skill_dictionary, name),
                            top_window.destroy()]).grid(row=0, column=0, sticky=W)
    # no reference is made to `job_focuses_dictionary` in a way that survives the function


root = Tk()
change_job_skills("Community Engagement")
root.mainloop()

虽然skill_dictionaryjob_focuses_dictionary 都在change_job_skills 的代码中使用,但skill_dictionary 用于定义lambda 函数,然后作为command 参数传递给Button。由于按钮稍后需要调用该函数,因此在其中保存了对 lambda 的引用,并且由于 lambda 的函数体引用了skill_dictionary,因此字典在函数返回时仍然存在。

但是,job_focuses_dictionary 仅被引用为 job_focuses_dictionary[key],从中检索一个值 - 字典本身不会传递给在函数外部维护对它的引用的任何东西,所以当函数返回时,字典是垃圾收集。

同样的问题,但更难发现。 (@acw1668 在 cmets 中也指出了这一点)

请注意,我还将您的参数 Name 重命名为 name,您应该为类型保留大写名称,为变量保留小写名称,符合 Python 标准命名,这有助于您和其他人更快地阅读和理解您的代码。不过与问题无关。

【讨论】:

  • 感谢您的回答。我实际上在更大范围内遇到了这个问题,并希望您的回答能解决我的问题,但我仍然感到困惑。 Here's a link to the .py。由于某种原因,前半部分,技能,工作完美(尽管在功能中定义。后半部分,工作重点,根本不起作用。管理应该默认选中,但不是。介意看看?
  • @Friend_Slayer666 是因为前半部分(技巧)使用的变量skill_dictionary仍然被Submit按钮的lambda函数引用,所以函数退出后不会被垃圾回收.
  • 我希望添加的信息能让问题更清楚。也不是说您可以拥有一个完整的对象连接图,这些对象在一个函数中存在,所有对象都相互引用,只要其中只有一个最终成为函数外部的引用,它们都会存在。但这通常不是一件好事,由于副作用和内存使用可能出现的问题(对于较大的数据结构或非常频繁创建的数据结构),请确保这是您想要发生的事情。
  • @Grismar 感谢您的详细解释。这是有道理的,但我永远不会想到它。我只是将 job_focuses_dictionary 添加到 lambda 中。
猜你喜欢
  • 2018-10-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-02-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多