我正在对来自this post的技术进行自己的调整,使用画布与文本小部件来更好地控制滚动行为。我的代码显示在下方。
一切正常,因为我想要它但由于某种原因我用来跟踪检查按钮值的trace
不起作用。控制台窗口中不会显示任何类型的错误。但是当我点击任何一个检查按钮时,我没有得到预期的打印消息(来自_cbWasClicked
)。最好我可以告诉该方法永远不会被调用。
我知道它必须是一个简单而明显的错误,但我很难过。我已经使用print
语句来确认100 IntVars
按预期实例化了。然后我故意拼错了.trace
中的方法名称,这次它产生了一个错误。因此,当我抽出那些诊断调整时,所有应该正在工作....它只是不是。有人可以告诉我我缺少什么吗?
环境是Windows 7上的Python 2.7。
import Tkinter as tk
class myCheckList(tk.Frame):
def __init__(self, root, *args, **kwargs):
tk.Frame.__init__(self, root, *args, **kwargs)
self.root = root
self.vsb = tk.Scrollbar(self, orient="vertical")
self.canvas = tk.Canvas(self, width=200, height=290,
relief=tk.GROOVE,bd=3,
scrollregion=(0,0,0,2020),
yscrollcommand=self.vsb.set,
yscrollincrement=20)
basecolor = self.canvas.cget('background')
self.vsb.config(command=self.canvas.yview)
self.canvas.grid(row=0,column=0,sticky=tk.NSEW,padx=(0,0),pady=0)
self.vsb.grid(row=0,column=1,sticky=tk.NS,padx=(0,0),pady=0)
for i in range(100):
cbv = tk.IntVar()
cbv.trace('w',self._cbWasClicked)
cb = tk.Checkbutton(self, background=basecolor,
variable=cbv,
text="Checkbutton #%s" % i)
self.canvas.create_window(5,20*i+5,anchor=tk.NW,window=cb)
self.canvas.bind_all('<MouseWheel>',
lambda event: self.canvas.yview_scroll(-1*event.delta/120, tk.UNITS))
def _cbWasClicked(self,*args):
print 'checkbox clicked'
if __name__ == "__main__":
root = tk.Tk()
myCheckList(root).grid(row=0,column=0,sticky=tk.W,padx=0,pady=0)
root.mainloop()
答案 0 :(得分:2)
经过多次摔跤和实验后找到它。事实证明,当我向班级trace
添加几行时__init__
完美无缺:
self.status = []
......然后,在循环内......
self.status.append((cb,cbv))
...告诉我垃圾收集是罪魁祸首。通过创建列表并在其中存储对象引用,它们不能被垃圾收集,因此.trace
仍然有效。
答案 1 :(得分:1)
首先,您应该在FOR周期中将self.
添加到cbv
和cb
。
其次,即使这样,它也只能用于最后一个复选框,因为每次迭代都会一次又一次地覆盖变量cbv
。
作为一种解决方法,我使用了一个在循环之前生成一步的vaiables(self.li
)列表。这样您就可以将每个复选框链接到自己的变量:
self.li = ['cbv' + str(i) for i in range(100)]
for i in range(100):
self.li[i] = tk.IntVar()
self.cb = tk.Checkbutton(self, background=basecolor,
variable=self.li[i],
text="Checkbutton #%s" % i)
self.li[i].trace('w', self._cbWasClicked)
self.canvas.create_window(5,20*i+5,anchor=tk.NW,window=self.cb)
...
这段代码对我来说很好。
然后,您需要以某种方式识别每个复选框。您可以使用内部变量name
来执行此操作,该变量作为第一个参数传递到callback
方法trace
方法中的def _cbWasClicked(self, name, *args):
print('checkbox %s clicked:' % name)
函数:
checkbox PY_VAR10 clicked:
checkbox PY_VAR99 clicked:
checkbox PY_VAR0 clicked:
在输出中你会得到这样的结果:
{{1}}