Tkinter TreeView使用self.after实现行闪烁功能失效求助
问题:TreeView编辑后行闪烁功能失效,直接设置标签正常
我实现了支持双击编辑单元格的EditableTreeView类,想在编辑完成后让被编辑行黄色闪烁固定时长。但用self.after实现闪烁逻辑时功能失效,直接设置标签能正常显示黄色背景,试了lambda写法也没用,求问题原因和解决办法。
我的实现代码:
import tkinter as tk from tkinter import ttk, filedialog import pandas as pd class EditableTreeView(ttk.TreeView): def __init__(self, application, *args, **kwargs): super().__init__(*args, **kwargs) self.bind('<Double-1>', self.on_double_click) self.application = application self.edit_stack = [] self.tag_configure("flash_yellow", background="yellow") def on_double_click(self, event): region_clicked = self.identify_region(event.x, event.y) if region_clicked != "cell": return column = self.identify_column(event.x) selected_iid = self.focus() selected_value = self.item(selected_iid) self.get_children() column_index = int(column[1:]) - 1 if column == "#0": return else: selected_text = selected_value.get("values")[column_index] column_box = self.bbox(selected_iid, column) entry_edit = ttk.Entry(self) entry_edit.editing_column_index = column_index entry_edit.editing_item_iid = selected_iid entry_edit.insert(0, selected_text) entry_edit.selection_range(0, tk.END) entry_edit.focus() entry_edit.place(x=column_box[0], y=column_box[1], w=column_box[2], h=column_box[3]) entry_edit.bind("<FocusOut>", self.on_entry_confirm) entry_edit.bind("<Return>", self.on_entry_confirm) entry_edit.bind("<Escape>", self.on_escape) def flash_yellow(self, iid): #self.item(selected_iid, tags=("flash_yellow")) self.after(100, self.item(iid, tags=("flash_yellow",))) self.after(500, self.item(iid, tags=())) @staticmethod def on_escape(event): event.widget.destroy() def on_entry_confirm(self, event): new_text = event.widget.get() selected_iid = event.widget.editing_item_iid column_index = event.widget.editing_column_index current_values = self.item(selected_iid).get("values") self.edit_stack.append((selected_iid, current_values)) current_values[column_index] = new_text self.item(selected_iid, values=current_values) # This adds a new row if last row is non-empty if selected_iid == self.get_children()[-1] and current_values != [""] * len(current_values): self.insert("", "end", values=("",) * len(current_values)) self.flash_yellow(selected_iid) event.widget.destroy()
注:如果直接替换flash_yellow函数内的代码为self.item(selected_iid, tags=("flash_yellow")),则可正常显示黄色背景。
问题原因
你当前的flash_yellow方法存在参数传递错误:
self.after(delay, func, *args)的第二个参数需要是可调用的函数对象,但你直接执行了self.item(iid, tags=("flash_yellow",)),并把执行结果(None)传给了after,导致延迟任务根本没正确注册,自然不会触发闪烁效果。- 直接执行
self.item(...)时会立刻修改标签,所以能看到黄色背景,但用after时因为传参错误,相当于没做任何延迟操作。
解决方案
修改flash_yellow方法,用lambda或者functools.partial把函数调用包装成可执行对象,让after能在指定延迟后正确触发:
方法1:使用lambda包装
def flash_yellow(self, iid): # 用lambda延迟执行标签设置操作 self.after(100, lambda: self.item(iid, tags=("flash_yellow",))) self.after(500, lambda: self.item(iid, tags=()))
方法2:使用functools.partial(需导入functools)
import functools def flash_yellow(self, iid): self.after(100, functools.partial(self.item, iid, tags=("flash_yellow",))) self.after(500, functools.partial(self.item, iid, tags=()))
修改后,after会在指定延迟后执行包装后的函数,正确完成标签的设置与清除,实现行的黄色闪烁效果。
内容的提问来源于stack exchange,提问作者Lost1
相关产品推荐
相关产品推荐

