Tkinter界面设计的复选框(Checkbutton)的补充介绍

众所周知,Python提供很多种图形界面(GUI)设计的库,其中最常见的库之一是tkinter模块,它是 Python 的标准 Tk GUI 工具包的接口[1]。

Tkinter库给用户提供了各种各样的组件,网站[2]介绍了这些组件的用法。但复选框(Checkbutton)组件[3]介绍的内容较少,所以本文对该组件的介绍做一些补充。

checkbox = ttk.Checkbutton(container,
                text='<checkbox label>',
                command=check_changed,
                variable=checkbox_var,
                onvalue='<value_when_checked>',
                offvalue='<value_when_unchecked>')

网页[3]中使用了以上代码介绍Checkbutton, 即复选框的参数。其中text是复选框的标记文字,command是该复选框被点按后触发的函数,variable是该复选框的值绑定的变量,onvalueoffvalue是在用户在变量中不愿用0、1而是愿意用其它值来代表复选框的开关状态时使用[3]。

本文在三个方面对Checkbutton的介绍进行一些补充。

一、事件绑定

很多时候,为了让触发函数的方式更为灵活,我们会建议用事件(event)绑定(bind)代替组件中的command。在这里设计一个程序,把Checkbutton的变量值和一个标签(Label)的显示同步,让Checkbutton被点击时,通过事件,把新的Checkbutton的变量值更新给标签。

程序如下:

from tkinter import *
from tkinter import ttk
from time import sleep

def checkChange(log):
    labl1['text'] = checkVar.get()

root = Tk()
root.geometry('333x333')
root.title('check box window')
frm = ttk.Frame(root)
frm.pack()
checkVar = BooleanVar()

chB1 = ttk.Checkbutton(frm, text="Check this please", variable=checkVar)
chB1.bind('<ButtonRelease>', checkChange)
chB1.pack()

labl1 = ttk.Label(frm, text=checkVar.get())
labl1.pack()

root.mainloop()

在这里,名为chB1的Checkbutton组件的<ButtonRelease>事件和checkChange绑定,表明鼠标按下该复选框,并松开后,checkChange函数会被触发。关于事件名的意思,见[4]。

以上程序的运行效果如下:

显然,该Label显示的值和checkVar(即该复选框的对应变量)的值最初相同,之后都是相反的。造成这个不合理的现象的原因在于,Checkbutton组件通过事件处理程序访问的值将始终是旧状态[5]。换句话说,当Checkbutton被点击后,其绑定的事件是在Checkbutton值改变前就产生的,所以在绑定的事件触发的函数运行时,Checkbutton值尚未改变,所以checkVar.get()读出的值是点击Checkbutton之前的值。当程序运行完后,Checkbutton值才改变。

为了证实这一点,现在在checkChange函数里增加一行sleep(1),让函数运行时等待一秒。

def checkChange(log):
    sleep(1)
    labl1['text'] = checkVar.get()

效果如下:

可以看出,当复选框被点击后,等了一秒钟,复选框里的勾才发生变化。这说明复选框被点击时,先执行被绑定的事件的函数,完成后才更新对应的变量数值。

所以,Checkbutton组件并不适合用这种事件绑定的做法更新其它组件的内容显示[5]。

二、变量追踪

command触发函数,使复选框被按下时,将复选框对应的变量值同步给其它组件,是可行的。

from tkinter import *
from tkinter import ttk
from time import sleep

def checkChange():
    labl1['text'] = checkVar.get()

root = Tk()
root.geometry('333x333')
root.title('check box window')
frm = ttk.Frame(root)
frm.pack()
checkVar = BooleanVar()

chB1 = ttk.Checkbutton(frm, text="Check this please", variable=checkVar, command=checkChange)
chB1.pack()

labl1 = ttk.Label(frm, text=checkVar.get())
labl1.pack()

root.mainloop()

但除了这种方法外,还有另一种方法,就是用变量追踪(trace)功能,追踪Checkbutton组件的变量的值的变化。当值变化时,更新其它组件。

Tkinter的变量有追踪(trace)的功能,可以注册一些追踪器,使得当变量值发生变化或其它操作时,触发一些函数。详细介绍见[6]。简单地说,trace_add添加一个追踪器,即添加一个在变量上发生一些操作时触发的函数;trace_remove删除追踪器;trace_info列出变量目前已注册的追踪器。

from tkinter import *
from tkinter import ttk
from time import sleep

def checkChange(a,b,c):
    sleep(1)
    labl1['text'] = checkVar.get()
    print(f"a={a},b={b},c={c}")
    print(checkVar.trace_info())

root = Tk()
root.geometry('333x333')
root.title('check box window')
frm = ttk.Frame(root)
frm.pack()
checkVar = BooleanVar()

chB1 = ttk.Checkbutton(frm, text="Check this please", variable=checkVar)
checkVar.trace_add('write', checkChange)
chB1.pack()

labl1 = ttk.Label(frm, text=checkVar.get())
labl1.pack()

root.mainloop()

程序里的这句checkVar.trace_add('write', checkChange)就是把“在checkVar值变化时触发checkChange”这个追踪器添加到checkVar上。

效果如下:

注意在追踪器触发时,会传递三个参数给checkChange函数。所以在这个函数中,添加了打印这三个参数的功能。于此同时,也添加打印trace_info的功能。每次点击复选框后,打印内容如下:

a=PY_VAR7,b=,c=write
[(('write',), '2480373178944checkChange')]

所以它传递了追踪器的代号以及触发的条件(这里是‘write’)。

另外trace_info是一个包含该变量注册的所有追踪器的列表。

三、初始状态

有的用户希望实现当程序启动时,复选框默认处于被选中的状态。这是可行的,只要其对应的变量的初始值为onvalue即可,这里onvalue=1

checkVar = BooleanVar(value=1)

用这句代码初始化checkVar即可。

效果如下:

四、小结

如果想让Checkbutton的值和其它组件显示的内容同步,或绑定,用事件绑定不是一个好的方法。但除了用command外,也可以用追踪器(trace)。另外,通过设置变量初始值,可以定义Checkbutton的初始状态。

参考资料

[1]Python GUI 编程(Tkinter) | 菜鸟教程

[2]Tkinter Tutorial

[3]Tkinter Checkbox

[4]python学习笔记:tkinter之事件(event)、事件处理(event handler)、事件绑定(event binding)、基于事件的动画(animation)_tkinter event-CSDN博客

[5]python - 当 ttk.Checkbutton 小部件的状态发生变化时,如何编写后续操作?_Stack Overflow中文网

[6]Tracing Tkinter variables in Python - GeeksforGeeks

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值