首页 > 解决方案 > Tkinter widget.cget('变量')

问题描述

如何使用cget('variable')方法获取对小部件控制变量的引用?我正在寻找一种使用返回的对象cget('variable')来查找关联tkinter.IntVar对象的解决方案。

import tkinter as tk

root = tk.Tk()

var = tk.IntVar()
print('tkinter variable is of type', type(var)) # <class 'tkinter.IntVar'>

button = tk.Checkbutton(root, text='Checkbutton 1', variable=var)
button.pack(side=tk.TOP, padx=10, pady=10)

# Now I attempt to retrieve "var", using cget('variable').
var2 = button.cget('variable')

print('cget("variable") returns an object of type', type(var2)) # <class '_tkinter.Tcl_Obj'>
print(var is var2) # False

root.mainloop()

标签: pythontkintertcltk

解决方案


为自己省去很多麻烦,只需将其存储IntVar在按钮上

var        = tk.IntVar()
button     = tk.Checkbutton(root, text='Checkbutton 1', variable=var)
button.var = var         # keep a reference on the button itself

或者像这样

button     = tk.Checkbutton(root, text='Checkbutton 1')
button.var = tk.IntVar()
button.configure(variable=button.var)

除非您的真正目标是在不需要参考的情况下获得价值,否则您可以这样做:

value = button.getvar(str(button.cget("variable")))
print(value)

作为替代方案,您可以使用我很久以前制作的这个小类。它主要只是自动化一切,但它也允许您将一些任意数据与Checkbutton.

class Checkbox(tk.Checkbutton):
    @property
    def var(self):
        return self.__var
        
    @property
    def value(self) -> int:
        return self.__var.get()
        
    @value.setter
    def value(self, value):
        self.__var.set(int(bool(value)))
        
    def __init__(self, master, data=None, on_change=None, on_read=None, **kwargs):
        self.__var = tk.IntVar() if not 'variable' in kwargs else kwargs['variable']
        tk.Checkbutton.__init__(self, master, **{**kwargs, 'variable':self.__var})
        self.data = self['text'] if not data else data
            
        if on_change:
            self.__var.trace('w', lambda *a:on_change(self))
            
        if on_read:
            self.__var.trace('r', lambda *a:on_read(self))

以下是一些示例用法

#example 1
def on_change(checkbox):
    print(checkbox.data, checkbox.value)

Checkbox(root, on_change=on_change, text='tester1').grid()
Checkbox(root, on_change=on_change, text='tester2').grid()

#-----------------------------------------------------------
#example 2
cbs = [
    Checkbox(root, text='test1'),
    Checkbox(root, text='test2'),
    Checkbox(root, text='test3'),
    Checkbox(root, text='test4'),
]

for i, cb in enumerate(cbs):
    cb.grid(row=0, column=i)
 
def get_values():
    print(*[f'{cb.data}:{cb.value}' for cb in cbs], sep='\n')
    
tk.Button(root, text="check", command=get_values).grid()

#-----------------------------------------------------------
#example 3
def on_read(checkbox):
    if checkbox.data is True:
        if checkbox.value:
            pass
        else:
            pass
    
cb = Checkbox(root, on_read=on_read, data=(someCondition is True), text='tester1')
cb.grid()
#...
something = cb.value  #triggers on_read

推荐阅读