问题描述
如何使用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()
解决方法
省去很多麻烦,只需将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,**{**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,text='tester2').grid()
#-----------------------------------------------------------
#example 2
cbs = [
Checkbox(root,text='test1'),Checkbox(root,text='test2'),text='test3'),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