如何在Tkinter中获取多个Checkbutton的状态?

时间:2012-01-26 22:57:28

标签: python user-interface checkbox tkinter

我正在编写一个小型的Tkinter / Python程序,它有一个可变长度的复选框列表(在运行时确定)。

我希望能够随时阅读所有复选框的状态,但我不确定应该怎么做。

以下是用于生成列表的代码段(从this post采用):

def relist(self):
    self.text.delete(1.0,END)
    p = subprocess.Popen (['ls', '/dev/'], stdout = subprocess.PIPE)
    lst = p.communicate()[0].split('\n')
    print lst
    for item in lst:
        v = tk.IntVar()
        cb = tk.Checkbutton(text="/dev/%s" % item, variable=v, command=self.cb(index))
        self.text.window_create("end", window=cb)
        self.text.insert("end", "\n") # to force one checkbox per line

我的虚拟处理程序:

def cb(self,idx):
    print ("var is %s", str(idx))
    lst[idx] = 1;

问题是我的处理程序被调用一次(当创建Checkbuttons时),而我希望每次点击Checkbutton(选中或取消选中)时调用它,并且当它被调用时,我希望它更新lst。

4 个答案:

答案 0 :(得分:3)

你的CheckButton命令正在执行回调,因为这就是你告诉它要做的事情。该命令应该是对单击检查按钮时tkinter可以执行的函数的引用。 Tkinter将事件对象传递给回调函数。请参阅此Effbot教程,但看起来您正在尝试实现其模式。您可以按照here的说明从event.widget属性获取对checkbutton的引用。最后,如果要在回调中引用变量,则需要将变量附加到“self”。

def relist(self):
    self.text.delete(1.0,END)       
    p = subprocess.Popen (['ls', '/dev/'], stdout = subprocess.PIPE)       
    lst = p.communicate()[0].split('\n')       
    print lst       
    self.var = tk.IntVar()
    for item in lst:           
        cb = tk.Checkbutton(text="/dev/%s" % item, variable=self.var, command=self.myCallback)
        self.text.window_create("end", window=cb)     
        self.text.insert("end", "\n") # to force one checkbox per line

def myCallback(self,event):
    var = self.var.get()
    print ("var is %s", str(var))

答案 1 :(得分:0)

我认为您所要求的内容可以来自here

对于每个item in lst,必须先为其创建不同的IntVar()变量,以指示每个复选框的独立状态。 除了手动创建它们之外我没有看到其他方式(我假设你没有数百个复选框)。 我将重新使用this回答中的代码并执行以下操作:

def relist(self):
    self.text.delete(1.0,END)       
    p = subprocess.Popen (['ls', '/dev/'], stdout = subprocess.PIPE)       
    lst = p.communicate()[0].split('\n')       
    print lst       
    self.var1 = tk.IntVar()
    self.var2 = tk.IntVar()
    self.var3 = tk.IntVar()
    .
    .
    . 
    vars = [self.var1,self.var2,self.var3,...]
    for item, var in zip(self.lst, vars):           
        cb = tk.Checkbutton(text="/dev/%s" % item, variable=var, command= lambda: self.myCallback(var))
        self.text.window_create("end", window=cb)     
        self.text.insert("end", "\n") # to force one checkbox per line

def myCallback(self,event,var):
    each_var = var.get()
    print ("var is %s", str(each_var))

答案 2 :(得分:0)

我有同样的问题。试试这个:

cb = tk.Checkbutton(text="/dev/%s" % item, variable=v, command=lambda: self.cb(index))

如果将方法作为lambda函数传递,它会对变量的每次更改执行方法。

答案 3 :(得分:0)

我个人不会使用tk.IntVar()/ tk.StringVar()等,但也许我应该这样做。 这可能不是最好的方法,但我认为这很容易理解。不要批评并告诉我什么是非常糟糕而不是pythonic所以我可以提高自己(我还是一个新手)。

我创建一个交互器,然后我在循环中创建我的检查按钮,在回调中,我在参数中传递了checkbutton和迭代器的值。

    ...
    self.listeColonneFile1 = []

    self.chbFile1 = []
    indice = 0
    for column in dfFile1.columns:
        btn = ttk.Checkbutton(self.frameCheckButtonsFile1,
            text=column,
            command=lambda i=indice, col=column: self.callback_onCheck(col, i)
        )

        self.chbFile1.append(btn)
        self.chbFile1[indice].grid(row = indice, column = 0, sticky="nw")
        self.chbFile1[indice].state(['!alternate'])
        indice += 1

在我的回调中,我有一个检查的所有checkButton的列表(好吧,不是ChB,但是它的文本或它的值):

def callback_onCheck(self, column, indice):
    if self.chbFile1[indice].instate(['selected']) == True:
        self.listeColonneFile1.append(column)
    else:
        self.listeColonneFile1.remove(column)

PS:dfFile1是一个pandas DataFrame,请参阅the doc