我在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()
答案 0 :(得分:1)
复选栏需要所选按钮的最大和当前数量的属性。然后,您需要在每次单击一个复选按钮时调用的命令。 更改变量后,在没有参数的情况下调用该命令。
如果可能,应该发布代码而不依赖于外部文件。在这种情况下,只需传递一个字符串列表。 (我在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变量传递时,它将被没有.get和.set方法的_tkinter.Tcl_Obj替换。所以命令需要引用IntVar实例作为chk [&#39;变量&#39;]。get不起作用。
答案 1 :(得分:0)
这可以通过在选中最大CheckButtons数时禁用所有未检查的CheckButtons来完成。禁用CheckButtons可以提高用户友好性,因为它为用户提供了一个视觉线索,可以不再检查按钮。如果我们没有禁用CheckButtons,用户可能会感到困惑,为什么当他试图单击CheckButton时没有任何反应。
为了实现此功能,我们必须将回调函数连接到每个CheckButton。回调函数计算检查的按钮数量,并相应地禁用或启用其他按钮。
我们要做的第一件事就是重写__init__
方法。 Checkbar
需要一个新参数,可以同时检查多少个Checkbuttons。我们还必须将回调函数连接到每个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
(var
参数来自我们之前使用过的functools.partial
。
完整的代码:
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
答案 2 :(得分:0)
我个人会使用一个列表列表。
我可以将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()