ttk.Treeview.focus()返回I001而非索引,如何正确更新树视图条目?
解决ttk.Treeview更新条目时的节点标识问题
问题说明
更新ttk.Treeview条目时,ttk.Treeview.focus()返回类似I001的节点标识字符串,而非预期的数字索引。之前通过截取标识最后一位作为索引的临时方案,在条目数量超过10条时会失效,属于不可靠的临时手段。
正确解决方法
方法1:直接更新节点值(推荐)
无需删除原节点再插入新节点,直接使用Treeview.item()方法修改选中节点的values属性,既保留原节点位置,又高效可靠。
修改后的update_record()函数:
def update_record(): selected_items = register.selection() if not selected_items: return # 无选中节点时直接返回 new_value = (sn.get(), bn.get(), cn.get()) for item in selected_items: register.item(item, values=new_value) # 直接更新节点值 # 清空输入框 sn.delete(0, END) bn.delete(0, END) cn.delete(0, END)
方法2:删除原节点后在原位置插入(如需重建节点)
若必须删除原节点再插入新节点,不要依赖节点标识的字符串内容,改用Treeview.index()获取节点在父节点下的索引位置:
def update_record(): selected_items = register.selection() if not selected_items: return new_value = (sn.get(), bn.get(), cn.get()) for item in selected_items: parent = register.parent(item) # 获取父节点(根节点为"") index = register.index(item) # 获取节点在父节点下的索引 register.delete(item) register.insert(parent, index, values=new_value) # 在原位置插入 # 清空输入框 sn.delete(0, END) bn.delete(0, END) cn.delete(0, END)
完整修改代码
以下是替换方法1后的完整代码,同时优化了选中事件的处理逻辑:
from tkinter import * from tkinter import ttk root = Tk() root.title("Treeview") root.geometry("650x450") root.resizable(True, True) # 定义列 columns = ("Seller", "Buyer", "Contract Number") # 创建Treeview register = ttk.Treeview(root, columns=columns, show="headings") register.grid(row=0, column=0, columnspan=3, padx=5, pady=5) # 设置表头 register.heading(columns[0], text="Seller Name") register.heading(columns[1], text="Buyer Name") register.heading(columns[2], text="Contract Number") # 设置列对齐 register.column(columns[0], anchor=CENTER) register.column(columns[1], anchor=CENTER) register.column(columns[2], anchor=CENTER) # 添加条目 def add_entry(): entry = (sn.get(), bn.get(), cn.get()) register.insert("", END, values=entry) sn.delete(0, END) bn.delete(0, END) cn.delete(0, END) ttk.Label(root, text="Add Entries below:", font=("Arial", 15)).grid(row=1, column=0, pady=5, padx=5, sticky=W) ttk.Label(root, text="Seller Name:").grid(row=2, column=0, pady=5, padx=5, sticky=W) ttk.Label(root, text="Buyer Name:").grid(row=3, column=0, pady=5, padx=5, sticky=W) ttk.Label(root, text="Contract Number:").grid(row=4, column=0, pady=5, padx=5, sticky=W) sn = ttk.Entry(root) bn = ttk.Entry(root) cn = ttk.Entry(root) sn.grid(row=2, column=1, sticky=W) bn.grid(row=3, column=1, sticky=W) cn.grid(row=4, column=1, sticky=W) add = ttk.Button(root, text="Add Entry", command=add_entry) add.grid(row=5, column=0, columnspan=3, padx=5, pady=5, sticky=W) # 更新模式变量 update = IntVar() # 选中事件处理:删除或填充更新内容 def item_selected(event): selected_items = register.selection() if not selected_items: return if update.get() == 0: for selection in selected_items: register.delete(selection) else: # 清空输入框并填充选中条目的内容 sn.delete(0, END), bn.delete(0, END), cn.delete(0, END) item_values = register.item(selected_items[0])["values"] sn.insert(0, item_values[0]), bn.insert(0, item_values[1]), cn.insert(0, item_values[2]) register.bind('<<TreeviewSelect>>', item_selected) # 更新记录函数 def update_record(): selected_items = register.selection() if not selected_items: return new_value = (sn.get(), bn.get(), cn.get()) for item in selected_items: register.item(item, values=new_value) # 清空输入框 sn.delete(0, END) bn.delete(0, END) cn.delete(0, END) cb = ttk.Checkbutton(root, text="Update Records (on click)", variable=update) cb.grid(row=6, column=0, padx=5, pady=5, sticky=W) up = ttk.Button(root, text="Update Record", command=update_record) up.grid(row=6, column=1, padx=15, pady=10, sticky=W) root.mainloop()
关键知识点
Treeview.focus()返回的是Tkinter内部生成的节点唯一标识(item ID),格式不固定,绝对不能依赖其字符串内容提取索引。Treeview.item(item_id, values=new_values)是更新节点内容的最优方式,无需修改节点位置或重建节点。Treeview.index(item_id)可获取节点在父节点下的索引位置,该方法不受节点ID格式影响,是可靠的位置获取方式。
内容的提问来源于stack exchange,提问作者Code-Killer
相关产品推荐
相关产品推荐

