如何控制带Scrollbar的Tkinter Treeview是否更新显示以提升性能
控制Treeview的UI更新开关
首先,你的核心需求是暂停/恢复Treeview的内容更新,避免频繁修改导致的UI卡顿。Tkinter确实会在你修改Treeview元素(比如调用item()方法)时自动触发屏幕刷新,我们可以通过一个状态标志来控制是否执行实际的更新操作,同时保留更新逻辑的运行(或者也可以暂停整个更新循环,看你需求)。
下面是修改后的完整代码,我会一步步解释关键改动:
from tkinter.ttk import * from tkinter import * root = Tk() root.geometry('800x800') root.bind('<Escape>', lambda x:root.destroy() ) class Run_item_Tree(Frame): def __init__(self, roots): Frame.__init__(self, roots) t = Treeview(self, selectmode=NONE, height=10) self.t = t t["columns"] = ("1", "2") t['show'] = 'headings' t.column("1", width=100, anchor='c') t.column("2", width=50, anchor='c') t.heading("1", text="Title") t.heading("2", text="UL") t.pack(fill =BOTH,side =LEFT) vsb = Scrollbar(self, orient="vertical", command=t.yview) vsb.pack(fill = Y,side = RIGHT) self.vsb = vsb t.configure(yscrollcommand=vsb.set) # 添加更新启用标志,默认开启 self.update_enabled = True self.pack() a = Run_item_Tree(root) item_num = 4000 for i in range(item_num): # 修正values数量,和定义的列数匹配 a.t.insert('',index=END,text = i,values = (i,i+1),tags=('pass',)) count = 0 def update_test(): global count # 只有启用更新时才修改Treeview内容 if a.update_enabled: a.t.item(a.t.get_children()[0],values = (count,count+1)) count= (count+1)%item_num root.after(100, update_test) def toggle_update(): # 切换更新状态 a.update_enabled = not a.update_enabled # 更新按钮文本,提示当前状态 btn['text'] = '暂停更新' if a.update_enabled else '恢复更新' btn = Button(root,text='暂停更新',command=toggle_update) btn.pack() root.after(100,update_test) root.mainloop()
关键改动说明:
- 在
Run_item_Tree类中添加了self.update_enabled布尔变量,用来标记是否允许Treeview更新UI。 - 实现了
toggle_update函数作为按钮回调:它会切换update_enabled的状态,同时更新按钮文本让用户直观了解当前状态。 - 在
update_test函数中增加判断:只有当update_enabled为True时,才执行a.t.item()的修改操作——暂停期间,count依然会递增,但不会触发Treeview的UI刷新,避免了不必要的性能消耗。
扩展:线程场景下的控制
如果你是在子线程中修改Treeview内容,记住Tkinter的UI操作必须在主线程执行,子线程不能直接调用item()方法。你可以通过主线程的after()方法传递修改请求,同时用update_enabled标志过滤这些请求:
import threading import time def thread_update(): global count while True: time.sleep(0.1) count = (count+1)%item_num # 把修改请求放到主线程执行,同时判断更新状态 if a.update_enabled: root.after(0, lambda: a.t.item(a.t.get_children()[0],values=(count,count+1)))
这样即使子线程在运行,只要update_enabled为False,就不会触发Treeview的UI更新,避免卡顿。
内容的提问来源于stack exchange,提问作者黃瀚嶙




