2

based on examples and Henry's help I have come up with the following code to sort the tree in a tkinter treeview, but it does not work. I do not get any errors but the tree is not sorted. Any help is appreciated.

def treeview_sort_column(tv, col, reverse):
 l = [(tv.set(k, col), k) for k in tv.get_children('')]
 l.sort(key=lambda t: int(t[0]), reverse=reverse)
 # ^^^^^^^^^^^^^^^^^^^^^^^
 for index, (val, k) in enumerate(l):
 tv.move(k, '', index)
 tv.heading(col,
 command=lambda: treeview_sort_column(tv, col, not reverse))
def SortTree():
 columns = ('#0',)
 for col in columns:
 tree.heading(col, text=col,
 command=lambda c=col: treeview_sort_column(tree, c, False))
asked Mar 20, 2019 at 19:16
4
  • 1
    Did you execute SortTree? You should get a _tkinter.TclError: Display column #0 cannot be set if you did when you do the sorting with the above code. Commented Mar 21, 2019 at 2:28
  • Hi, I do run SortTree (I have some print statements to make sure) and I do not get any errors if I use columns = ('#0',), if I use columns = ('#0') without a comma then I get _tkinter.TclError: Invalid column index # Commented Mar 21, 2019 at 7:55
  • I feel like I am guessing with this whole code because I cannot seem to find any documentation on this, and examples that I find, they sort other columns, not the tree. A tree item can have features such as text, tag, iid, etc and I am sure I need to specify which one to sort on, but I don't know how to. Any sample code would be appreciated. Commented Mar 21, 2019 at 8:05
  • I had shown a sample below to just sort on first column. Commented Mar 21, 2019 at 8:20

2 Answers 2

10

Since you are just adding the command to column #0, you don't have to put it in a loop.

from tkinter import ttk
import tkinter as tk
root = tk.Tk()
tree = ttk.Treeview(root,height=10)
tree.pack()
def treeview_sort_column(tv, col, reverse):
 l = [(tv.item(k)["text"], k) for k in tv.get_children()] #Display column #0 cannot be set
 l.sort(key=lambda t: t[0], reverse=reverse)
 for index, (val, k) in enumerate(l):
 tv.move(k, '', index)
 tv.heading(col, command=lambda: treeview_sort_column(tv, col, not reverse))
tree.heading("#0", command=lambda : treeview_sort_column(tree, "#0", False))
for i in range(10):
 tree.insert("",0,text=i)
root.mainloop()
answered Mar 21, 2019 at 8:03
Sign up to request clarification or add additional context in comments.

3 Comments

Thanks again, it was very helpful! Unfortunately I do not have enough Reputation to upvote your answer....
If it helped, you can check it as the accepted answer.
For explanation: treeview.set can apparently not be called on column "#0". So instead of doing that, a different way of getting the value of the treeview items, according to which we want to sort the items. This is apparently done by treeview.item(item)["text"], avoiding the error.
1

As I wanted to sort by column values alphabetically on clicking the specific column header I made an addition to the function in the answer of @Henry Yik and wanted to post for people with the same question in the future.

def treeview_sort_column(tv, col, reverse):
 column_index = self.tree["columns"].index(col)
 l = [(str(tv.item(k)["values"][column_index]), k) for k in tv.get_children()]
 l.sort(key=lambda t: t[0], reverse=reverse)
 for index, (val, k) in enumerate(l):
 tv.move(k, '', index)
 
 tv.heading(col, command=lambda: treeview_sort_column(tv, col, not reverse))
answered Aug 27, 2021 at 9:30

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.