【问题标题】:How to get the state of multiple Checkbuttons in Tkinter?如何在 Tkinter 中获取多个 Checkbutton 的状态?
【发布时间】:2012-02-20 01:18:25
【问题描述】:

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

我希望能够随时读取所有复选框的状态,但我不确定我应该如何去做。

这里是生成列表的代码sn-p(来自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。

【问题讨论】:

  • 有效吗? self.cb(index) 中的 index 定义在哪里?
  • 请详细说明?在上面的代码中,为每个创建的复选框调用一次 cb,但仅在创建复选框时调用。调用时,cb 正在打印“var is ”(每个复选框的 idx 不同)。但问题是当一个复选框被修改(选中/取消选中)时,cb 没有被调用

标签: python user-interface checkbox tkinter


【解决方案1】:

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

【讨论】:

  • 感谢您的回复。我的问题是,每次单击复选框时都不会调用回调方法(用于多个复选框),在创建复选框时它们都只被调用一次。输出总是“var is 0”重复。此外,如果我在 myCallback 定义中包含“事件”,我会收到错误“TypeError:myCallback() 恰好需要 2 个参数(给定 1 个)”
  • 那么有没有办法将索引传递给回调方法?
  • 使用事件对象获取复选框对象。如果需要变量,就是变量属性。
  • 这会导致同一个变量与多个复选框相关联。这不是你应该使用复选框的方式——每个复选框都应该有自己的变量。
【解决方案2】:

我认为你所要求的可以来自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))

【讨论】:

    【解决方案3】:

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

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

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

    【讨论】:

      【解决方案4】:

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

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

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

      在我的回调中,我有一个所有被检查的 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 是一个 pandas DataFrame,见the doc

      【讨论】:

        猜你喜欢
        • 2023-03-14
        • 2021-02-06
        • 2013-05-22
        • 1970-01-01
        • 1970-01-01
        • 2023-04-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多