动态更新Tkinter组件
我在一个应用程序中控制连接到树莓派的各种传感器,写了一个Python脚本来读取和更新这些传感器的数值,并把它们显示在用tkinter创建的图形界面上的一些标签里。
这个图形界面有一个“开始”按钮,还有几个标签用来显示不同传感器读取到的数值。
当我点击“开始”按钮时,程序会执行一些配置和设置的操作,然后依次读取大约二十个模拟传感器的数值,并把这些数值写入对应的标签中。
我遇到的问题是,标签的更新只在“开始”按钮的处理程序结束后才会发生,也就是等程序重新进入主循环时才更新。因此,虽然脚本在控制和读取传感器数值方面工作正常,最后也能得到更新后的数值,但由于读取传感器需要一些时间,大约20秒,所以你会感觉点击“开始”后,什么都没有发生,等了20秒(有时甚至更久,因为有些传感器的响应时间更长)。
为了做一些检查,我写了一个非常简单的脚本,下面是这个脚本(实际的生产脚本因为涉及到传感器管理部分比较复杂):
import time
import tkinter as tk
from tkinter import ttk
def StartMain():
for i in range(10):
time.sleep(1)
lbl01.config(text=i)
print(i)
def ResMain():
lbl01.config(text="")
mainw = tk.Tk()
mainw.title("SyncLBL")
mainw.geometry("500x100+400+300")
mainw.resizable(False, False)
lbl01 = ttk.Label(text="",borderwidth=5, relief="ridge")
lbl01.grid(column=3, row=1,sticky="EW",padx=5,pady=2,ipadx=50, ipady=5)
StartButton=ttk.Button(text="START",command=StartMain)
StartButton.grid(column=0,row=3,sticky="EW",padx=5,pady=2,ipadx=50, ipady=5)
ResButton=ttk.Button(text="RESET",command=ResMain)
ResButton.grid(column=5,row=3,sticky="EW",padx=5,pady=2,ipadx=50, ipady=5)
mainw.mainloop()
当我在控制台点击“开始”按钮时,我看到计数每秒增加一次,而界面上的标签只有在“开始”程序结束时才更新,显示最后的计数值。
我该怎么做才能在计数进行时看到标签的实时更新呢?
1 个回答
0
如果你的传感器需要花费几百毫秒以上的时间来获取数据,那么让界面快速响应的唯一办法就是在一个单独的线程或进程中检查传感器。
你可以启动一个线程来收集数据,然后立刻返回,这样mainloop
就可以继续处理其他事件。这个线程可以在数据准备好时向主线程发送一个虚拟事件。然后,你可以在主线程中绑定这个虚拟事件,从一个线程安全的队列中获取数据,并更新界面。或者,你的主界面线程也可以每隔几百毫秒检查一次队列,当数据准备好时再更新界面。