代码之家  ›  专栏  ›  技术社区  ›  mohsen amini

TKinter中有一定数量的选项

  •  -1
  • mohsen amini  · 技术社区  · 7 年前

    我在Tkinter中做了一个包含许多项目的复选框,但我希望用户只能选择等于或小于一定数量的项目。这是我当前的代码:

    from tkinter import *
    
    class Checkbar(Frame):
        def __init__(self, parent=None, picks=[], side=LEFT, anchor=W):
            Frame.__init__(self, parent)
    
            self.vars = []
            for pick in picks:
                var = IntVar()
                chk = Checkbutton(self, text=pick, variable=var)
                chk.pack(side=side, anchor=anchor, expand=YES)
                self.vars.append(var)
    
        def state(self):
            return [var.get() for var in self.vars]
    
    
    root = Tk()
    
    lng = Checkbar(root, range(10))
    lng.pack(side=TOP,  fill=BOTH)
    
    root.mainloop()
    
    3 回复  |  直到 7 年前
        1
  •  1
  •   Terry Jan Reedy    7 年前

    检查栏需要检查的最大和当前按钮数的属性。然后,您需要一个在每次单击checkbutton时调用的命令。调用命令时不带参数 之后 变量已更改。

    如果可能,代码应该在不依赖于外部文件的情况下发布。在这种情况下,只需传递一个字符串列表。(我在Aran Fey编辑之前复制了。)

    from tkinter import *
    
    def checkmax(bar, var):
        # called after the intvar is changed
        def _check():
            print(bar.numpicks, var.get())
            if var.get():  # checked
                if bar.numpicks < bar.maxpicks:
                    bar.numpicks += 1
                else:
                    var.set(0)
            else:             # unchecked
                bar.numpicks -= 1
        return _check
    
    
    class Checkbar(Frame):
       def __init__(self, parent=None, picks=[], maxpicks=2, side=LEFT, anchor=W):
          Frame.__init__(self, parent)
          self.maxpicks = maxpicks
          self.numpicks = 0
          self.vars = []
          for pick in picks:
             var = IntVar()
             chk = Checkbutton(self, text=pick, variable=var,
                               command=checkmax(self, var))
             chk.pack(side=side, anchor=anchor, expand=YES)
             self.vars.append(var)
    
    
       def state(self):
            return map((lambda var: var.get()), self.vars)
    
    
    
    if __name__ == '__main__':
       root = Tk()
       lng = Checkbar(root, ['a', 'b', 'c', 'd'], 2)
    
       lng.pack(side=TOP,  fill=BOTH)
    
       lng.config(relief=GROOVE, bd=2)
    
       def allstates():
          print( list(lng.state() ) )
    
       Button(root, text = 'Quit', command = root.quit).pack(side = RIGHT)
       Button(root, text = 'submit', command = allstates).pack(side = RIGHT)
       root.mainloop()
    

    您应该为可检查的最大编号添加标签。

    补充说明:当Python IntVar作为Checkbutton变量传递时,它将被一个\u tkinter替换。没有的Tcl\u Obj。获取和。设置方法。因此,该命令需要引用IntVar实例作为chk['variable']。get不起作用。

        2
  •  0
  •   Aran-Fey Kevin    7 年前

    这可以通过在选中最大数量的复选按钮时禁用所有未选中的复选按钮来实现。禁用CheckButtons可以提高用户友好度,因为这会给用户一个视觉线索,即不能再检查更多的按钮。如果我们没有禁用复选按钮,用户可能会感到困惑,为什么在尝试单击复选按钮时什么都没有发生。


    为了实现此功能,我们必须将回调函数连接到每个CheckButton。回调函数统计检查的按钮数,并相应地禁用或启用其他按钮。

    我们要做的第一件事是重写 __init__ 方法这个 Checkbar 需要一个新参数同时可以检查多少个复选按钮。我们还必须将回调函数连接到每个CheckButton。我用过 functools.partial 将checkbutton的变量绑定到回调函数。

    def __init__(self, parent=None, picks=[], maxselect=1, side=tk.LEFT,
                       anchor=tk.W):
        super().__init__(parent)
    
        self.maxselect = maxselect
    
        # store all variables and checkbuttons; the callback function
        # needs access to them
        self._vars = []
        self._checkbuttons = []
    
        for pick in picks:
            var = tk.IntVar()
            # bind the callback function to each checkbutton
            chk = tk.Checkbutton(self, text=pick, variable=var,
                                 command=partial(self._var_toggled, var))
            chk.pack(side=side, anchor=anchor, expand=tk.YES)
    
            self._vars.append(var)
            self._checkbuttons.append(chk)
    

    现在只剩下实现回调函数了。只需计算选中了多少个复选按钮,并相应地启用或禁用它们:

    def _var_toggled(self, var):
        # count how many checkbuttons are checked
        num = sum(v.get() for v in self._vars)
    
        if num == self.maxselect:
            # if we're at maxselect, disable all unchecked checkbuttons
            for var, chk in zip(self._vars, self._checkbuttons):
                if not var.get():
                    chk['state'] = tk.DISABLED
        else:
            # otherwise, re-enable all checkbuttons
            for chk in self._checkbuttons:
                chk['state'] = tk.NORMAL
    

    (The var 参数来自 functools。部分的 我们之前使用过。)


    完整代码:

    from functools import partial
    import tkinter as tk
    
    class Checkbar(tk.Frame):
        def __init__(self, parent=None, picks=[], maxselect=1, side=tk.LEFT,
                           anchor=tk.W):
            super().__init__(parent)
    
            self.maxselect = maxselect
    
            # store all variables and checkbuttons; the callback function
            # needs access to them
            self._vars = []
            self._checkbuttons = []
    
            for pick in picks:
                var = tk.IntVar()
                # bind the callback function to each checkbutton
                chk = tk.Checkbutton(self, text=pick, variable=var,
                                     command=partial(self._var_toggled, var))
                chk.pack(side=side, anchor=anchor, expand=tk.YES)
    
                self._vars.append(var)
                self._checkbuttons.append(chk)
    
        def _var_toggled(self, var):
            # count how many checkbuttons are checked
            num = sum(v.get() for v in self._vars)
    
            if num == self.maxselect:
                # if we're at maxselect, disable all unchecked checkbuttons
                for var, chk in zip(self._vars, self._checkbuttons):
                    if not var.get():
                        chk['state'] = tk.DISABLED
            else:
                # otherwise, re-enable all checkbuttons
                for chk in self._checkbuttons:
                    chk['state'] = tk.NORMAL
    
        3
  •  0
  •   Mike - SMT    7 年前

    我个人会使用一个列表列表。

    我可以分配 Checkbutton() 以及相应的 IntVar() 列表中的列表。

    这将允许我检查每个索引的IntVar()状态,并相应地锁定或解锁复选按钮。

    看看下面的代码,如果您有任何问题,请告诉我。

    from tkinter import *
    
    class Checkbar(Frame):
        def __init__(self, parent=None, picks=[], side=LEFT, anchor=W):
            Frame.__init__(self, parent)
    
            self.vars = []
    
            for pick in picks:
                var = IntVar()
                # appending self.vars with a list of 2 objects at each index.
                self.vars.append([Checkbutton(self, text=pick, command=self.check_count, variable = var), var])
                self.vars[pick][0].grid(row=0, column=pick)
                self.vars[pick][0].bind("<Configure>")
    
        # each time a Checkbutton is selected this method runs.
        def check_count(self):
            counter = 0
            # if the Checkbutton being looked at is check it will add a counter
            for cbtn in self.vars:
                if cbtn[1].get() == 1:
                    counter += 1
            # if the counter reaches 3 then all Checkbuttons not selected will grey out.
            if counter == 3:
                for cbtn in self.vars:
                    if cbtn[1].get() != 1:
                        cbtn[0].config(state="disabled")
            # if counter not 3 then all Checkbuttons are normal.
            else:
                for cbtn in self.vars:
                    cbtn[0].config(state="normal")
    
    
    if __name__ == "__main__":
        root = Tk()
        Checkbar(root, range(10)).pack(fill=BOTH)
        root.mainloop()