简体   繁体   English

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

[英]How to get the state of multiple Checkbuttons in Tkinter?

I am writing a small Tkinter/Python program, that has a list of checkboxes with variable length (determined at run time). 我正在编写一个小的Tkinter / Python程序,它有一个可变长度的复选框列表(在运行时确定)。

I want to be able to read the state of all the checkboxes at any time, but I am not sure how I should go about that. 我希望能够随时阅读所有复选框的状态,但我不确定应该怎么做。

Here's the code snippet for generating the list (adopted from 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

And my dummy handler: 我的虚拟处理程序:

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

The problem is that my handler is getting called once (when the Checkbuttons are created), whereas I want it to get called everytime a Checkbutton is clicked (checked or unchecked), and when it is called, I want it to update lst. 问题是我的处理程序被调用一次(当创建Checkbuttons时),而我希望每次单击Checkbutton (选中或取消选中)时调用它,并且在调用它时,我希望它更新lst。

Your CheckButton command is executing the callback because that's what you are telling it to do. 你的CheckButton命令正在执行回调,因为这就是你告诉它要做的事情。 The command is supposed to be a reference to a function that tkinter can execute when the checkbutton is clicked. 该命令应该是对单击检查按钮时tkinter可以执行的函数的引用。 Tkinter passes the event object to the callback function. Tkinter将事件对象传递给回调函数。 See this Effbot tutorial, but it looks like you are trying to implement their pattern already. 请参阅此Effbot教程,但看起来您正在尝试实现其模式。 You can get a reference to the checkbutton from the event.widget attribute as explained here . 你可以从event.widget属性的checkbutton的引用,说明这里 Finally, you need to attach your variable to "self" if you want to refer to it in the callback. 最后,如果要在回调中引用变量,则需要将变量附加到“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))

I think what you have asked for can be derived from here . 我想你所要求的可以从这里得到

For each item in lst it must be previously created different IntVar() variable, just to indicate independent state of each checkbox. 对于item in lst每个item in lst它必须先前创建不同的IntVar()变量,只是为了指示每个复选框的独立状态。 I do not see other way than to create them manually (I assume you don't have hundred of checkboxes). 除了手动创建它们之外我没有看到其他方式(我假设你没有数百个复选框)。 I will re-use the code from this answer and do the following: 我将重新使用答案中的代码并执行以下操作:

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))

I had the same issue. 我遇到过同样的问题。 Try this one: 试试这个:

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

If you pass method as lambda function it executes the method on every change of the variable. 如果将方法作为lambda函数传递,它会在变量的每次更改时执行该方法。

Personally i don't use a tk.IntVar() / tk.StringVar() etc. but maybe i should. 我个人不使用tk.IntVar()/ tk.StringVar()等,但也许我应该。 It may not be the best way to do that but i think it's pretty much easy to understand. 这可能不是最好的方法,但我认为这很容易理解。 don't hesitate to criticize and tell me what's really bad and not pythonic so i can improve myself (i'm still a newbie). 不要犹豫批评并告诉我什么是非常糟糕而不是pythonic所以我可以提高自己(我还是一个新手)。

i make an interator then i create my checkbuttons in a loop and in the callback I pass in parameter the value of the checkbutton and the iterator. 我创建一个交互器,然后我在循环中创建我的检查按钮,在回调中,我在参数中传递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

In my callback, i have a list of all the checkButtons which are checked (well, not the ChB but its text or its value) : 在我的回调中,我有一个列表,其中包含所有检查的checkButtons(好吧,不是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 is a pandas DataFrame, see the doc PS:dfFile1是一个pandas DataFrame,请参阅doc

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM