跟踪无法处理Python TKinter checkbutton控件

时间:2014-01-10 22:07:38

标签: python-2.7 tkinter

我正在对来自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()

2 个答案:

答案 0 :(得分:2)

经过多次摔跤和实验后找到它。事实证明,当我向班级trace添加几行时__init__完美无缺:

self.status = []

......然后,在循环内......

    self.status.append((cb,cbv))

...告诉我垃圾收集是罪魁祸首。通过创建列表并在其中存储对象引用,它们不能被垃圾收集,因此.trace仍然有效。

答案 1 :(得分:1)

首先,您应该在FOR周期中将self.添加到cbvcb。 其次,即使这样,它也只能用于最后一个复选框,因为每次迭代都会一次又一次地覆盖变量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}}