Python 3.3.2 tkinter ttk TreeView 每列排序仅按最后一列排序?

标签 python sorting treeview tkinter ttk

我正在尝试使用标题“command”标记获得一个简单的 ttk TreeView 表,并按列排序,但它似乎无法正常工作。我正在使用这个问题的答案来实现功能:Tk treeview column sort

我的代码:

import tkinter as tk
from tkinter import ttk

def treeview_sort_column(tv, col, reverse):
    print('sorting %s!' % col)
    l = [(tv.set(k, col), k) for k in tv.get_children('')]
    l.sort(reverse=reverse)

    # rearrange items in sorted positions
    for index, (val, k) in enumerate(l):
        print('Moving Index:%r, Value:%r, k:%r' % (index, val, k))
        tv.move(k, '', index)

    # reverse sort next time
    tv.heading(col, command=lambda: treeview_sort_column(tv, col, not reverse))

cols = ('name', 'path', 'time', 'pb')

root = tk.Tk()
root.geometry("700x500")
listbox = ttk.Treeview(root, columns=cols, show="headings")
for each in ('name', 'path', 'time','pb'):
    listbox.heading(each,text=each.capitalize(),command=lambda: treeview_sort_column(listbox, each, False))
    listbox.column( each, width=tk.font.Font().measure(each.title() ))
    if not each == 'path':
        listbox.column(each,stretch=False)
    if not each == 'name':
        listbox.column( each, anchor='center')

listbox.pack(expand=True, fill=tk.BOTH)

root.mainloop()

我遇到的问题是每次我运行它时,它只按最后一列排序,而不是按你点击的列排序(用 treeview_sort_column 函数中的打印语句验证)。单击结果窗口中的任何列得到的输出:

sorting pb!
sorting pb!
sorting pb!
sorting pb!
sorting pb!
sorting pb!
sorting pb!
sorting pb!

如果我通过在循环后添加它来将 for 循环中每个命令的动态创建更改为显式命令,那么它会按预期工作(即每列自行排序)。

listbox.heading('name', command=lambda: treeview_sort_column(listbox, 'name', False))
listbox.heading('path', command=lambda: treeview_sort_column(listbox, 'path', False))
listbox.heading('time', command=lambda: treeview_sort_column(listbox, 'time', False))
listbox.heading('pb', command=lambda: treeview_sort_column(listbox, 'pb', False))

产生:

sorting name!
sorting name!
sorting path!
sorting path!
sorting time!
sorting time!
sorting pb!
sorting pb!

显然,这是一个非常简单的示例,我的最终应用程序实际上将数据插入到列中(也有更多的列),但由于我什至无法使这个简化版本工作,我不知所措。我的循环有什么问题导致 lambda 函数搞砸了?

我的系统:

  • Windows 7,64 位
  • python 3.3.2

最佳答案

您应该以其他方式使用 lambda。在您的代码中,每个 lambda 都会获得指向同一变量的指针,这就是为什么所有函数都做同样的事情。例如,您应该复制变量以使 lambda 唯一。一个如何做的例子:

for each in ('name', 'path', 'time','pb'):
    listbox.heading(each,text=each.capitalize(),command=lambda each_=each: treeview_sort_column(listbox, each_, False))

简单的例子:

funcs = []
for item in ('abc', 'def', 'ghi'):
    funcs.append(lambda : print(item))
for f in funcs:
    f()

它打印:

ghi
ghi
ghi

但是具有固定 lambda 的版本:

funcs = []
for item in ('abc', 'def', 'ghi'):
    funcs.append(lambda item_=item: print(item_))
for f in funcs:
    f()

打印

abc
def
ghi

关于Python 3.3.2 tkinter ttk TreeView 每列排序仅按最后一列排序?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20079989/

相关文章:

python - 根据条件在 DataFrame 中设置值

python - numpy:将 argsort 应用于数组

java - Java 中的 Arrays.asList 排序

javascript - 如何有条件地为 Material ui TreeView 组件设置扩展属性

python - 根据条件分成不同的行

java - 使用比较器实例化 TreeMap,该比较器应该能够访问所述 TreeMap

objective-c - 对 NSSet 进行排序的最有效方法是什么?

c# - 为什么只有当鼠标悬停在 TreeNode 的文本区域上时,TreeView.NodeMouseHover 事件才会发生?

水平方向的WPF TreeView?

python - Pandas 将文本文件转换为 CSV