如何在Tkinter Treeview中对Badge列数字进行降序排序?
问题:Treeview按Badge列降序排序失效的原因及修复
我希望将Treeview中的Badge列数字按降序(9、7、5、4、3、1)排列,排序时行的顺序也随之改变,期望得到如下结果:
5,"Frank","9"
3,"Daniel","7"
4,"Leonard","5"
1,"Jack","4"
6,"Robert","3"
2,"Tom","1"
但我的代码无法实现该效果,请问代码中存在什么问题?
原代码
from tkinter import * from tkinter import ttk ws = Tk() ws.title('PythonGuides') ws.geometry('400x300') ws['bg']='#fb0' data = [ [1,"Jack","4"], [2,"Tom","1"], [3,"Daniel","7"], [4,"Leonard","5"], [5,"Frank","9"], [6,"Robert","3"], ] tv = ttk.Treeview(ws) tv['columns']=('Rank', 'Name', 'Badge') tv.column('#0', width=0, stretch=NO) tv.column('Rank', anchor=CENTER, width=80) tv.column('Name', anchor=CENTER, width=80) tv.column('Badge', anchor=CENTER, width=80) tv.heading('#0', text='', anchor=CENTER) tv.heading('Rank', text='Id', anchor=CENTER) tv.heading('Name', text='rank', anchor=CENTER) tv.heading('Badge', text='Badge', anchor=CENTER) tv.pack() def func1(): rows = [(tv.set(item, "Badge"), item) for item in tv.get_children('')] rows.sort(reverse=True) for index, record in enumerate(data): Rank = record[0] Name = record[1] Badge = record[2] datagrid = [Rank, Name, Badge] tv.insert(parent='', index='end', values=(datagrid)) button = Button(ws, text="Button", command = func1) button.place(x=1, y=1) ws.mainloop()
代码存在的问题
- Treeview未初始化加载数据:原代码没有把
data中的内容插入到Treeview,点击按钮前Treeview是空的,导致排序逻辑无法获取有效行数据。 - 排序逻辑未作用于Treeview行顺序:代码中仅对Badge值和行ID的列表做了排序,但没有根据排序结果重新调整Treeview的行顺序,反而直接循环原始
data插入新行,完全没用到排序后的结果。 - 字符串排序而非数字排序:
data中的Badge值是字符串类型(如"9"、"7"),直接排序会遵循字符串ASCII规则,若出现两位数字(如"10"和"2")会得到错误排序结果。 - 未清理原有数据:点击按钮时未删除Treeview中的旧行,直接插入新数据会导致内容重复堆积。
修正后的代码
from tkinter import * from tkinter import ttk ws = Tk() ws.title('PythonGuides') ws.geometry('400x300') ws['bg']='#fb0' data = [ [1,"Jack","4"], [2,"Tom","1"], [3,"Daniel","7"], [4,"Leonard","5"], [5,"Frank","9"], [6,"Robert","3"], ] tv = ttk.Treeview(ws) tv['columns']=('Rank', 'Name', 'Badge') tv.column('#0', width=0, stretch=NO) tv.column('Rank', anchor=CENTER, width=80) tv.column('Name', anchor=CENTER, width=80) tv.column('Badge', anchor=CENTER, width=80) tv.heading('#0', text='', anchor=CENTER) tv.heading('Rank', text='Id', anchor=CENTER) tv.heading('Name', text='rank', anchor=CENTER) tv.heading('Badge', text='Badge', anchor=CENTER) tv.pack() # 初始化加载数据到Treeview for record in data: tv.insert(parent='', index='end', values=record) def func1(): # 获取所有行的Badge值(转成数字)和行ID,按数字降序排序 rows = [(int(tv.set(item, "Badge")), item) for item in tv.get_children('')] rows.sort(reverse=True, key=lambda x: x[0]) # 清空Treeview原有内容 for item in tv.get_children(''): tv.delete(item) # 根据排序结果重新插入数据 for _, item_id in rows: # 获取该行的原始数据 values = tv.item(item_id)['values'] tv.insert(parent='', index='end', values=values) button = Button(ws, text="Button", command=func1) button.place(x=1, y=1) ws.mainloop()
内容的提问来源于stack exchange,提问作者aesh
相关产品推荐
相关产品推荐

