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

时间:2021-08-04 07:43:11

I am trying to get a simplistic ttk TreeView table going with per-column sorting using the heading 'command' tag, but it doesn't seem to work right. I'm using the answer to this question for implementing the functionality: Tk treeview column sort

我试图得到一个简单的ttk TreeView表,使用标题'command'标记进行每列排序,但它似乎不正常。我正在使用这个问题的答案来实现功能:Tk treeview列排序

My code:

我的代码:

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()

The problem I am running into is every time I run this, it only sorts by the last column, not by the column your clicking on (verified with the print statement in the treeview_sort_column function). Output I get from clicking on any column in the resulting window:

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

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

If I change from dynamic creation of each command in the for loop to explicit ones by adding this after the loop then it works as expected (i.e. each column sorts itself).

如果我通过在循环之后添加它来从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))

produces:

生产:

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

Obviously this is a very simplistic example, and my final application actually inserts data into the columns (also has more columns) but since I can't even get this simplified version to work, I'm at a loss. What is wrong with my loop that's causing the lambda functions to get screwed up?

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

My system:

我的系统:

  • Windows 7, 64 bit
  • Windows 7,64位
  • Python 3.3.2
  • Python 3.3.2

1 个解决方案

#1


8  

You should use lambda in other way. In your code every lambda gets a pointer to the same variable, that is why all functions do the same thing. You should, e.g, copy variable to make lambda unique. An example how to do it:

你应该以其他方式使用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))

Simple example:

简单的例子:

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

It prints:

它打印:

ghi
ghi
ghi

But version with fixed lambda:

但是具有固定lambda的版本:

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

prints

版画

abc
def
ghi

#1


8  

You should use lambda in other way. In your code every lambda gets a pointer to the same variable, that is why all functions do the same thing. You should, e.g, copy variable to make lambda unique. An example how to do it:

你应该以其他方式使用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))

Simple example:

简单的例子:

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

It prints:

它打印:

ghi
ghi
ghi

But version with fixed lambda:

但是具有固定lambda的版本:

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

prints

版画

abc
def
ghi