I used an exapmple from a tutorial to sort columns in treeview. It works for 2nd and 3rd column, but not for the 1st column. If I click on the heading I get this Error:
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Python311\Lib\tkinter\__init__.py", line 1967, in __call__
return self.func(*args)
^^^^^^^^^^^^^^^^
File "D:\...\Test_Treeview_book.py", line 20, in <lambda>
tv.heading('#0', text='Name', command=lambda: sort(tv, '#0'))
^^^^^^^^^^^^^^
File "D:\...\Test_Treeview_book.py", line 14, in sort
itemlist.sort(key=lambda x: tv.set(x, col))
File "D:\...\Test_Treeview_book.py", line 14, in <lambda>
itemlist.sort(key=lambda x: tv.set(x, col))
^^^^^^^^^^^^^^
File "C:\Python311\Lib\tkinter\ttk.py", line 1434, in set
res = self.tk.call(self._w, "set", item, column, value)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
_tkinter.TclError: Display column #0 cannot be set
I have this small test program as reference and couldn't find the failure. I am thankful for any hint to solve this issue or is it not possible to sort 1st column at all, because it's a tree?
import tkinter as tk
from tkinter import ttk
from pathlib import Path
root = tk.Tk()
root.grid_rowconfigure(0, weight=1)
root.grid_columnconfigure(0, weight=1)
paths = Path('.').glob('**/*')
def sort(tv, col): # Doesn't work on 1st column '#0'
itemlist = list(tv.get_children(''))
itemlist.sort(key=lambda x: tv.set(x, col))
for index, iid in enumerate(itemlist):
tv.move(iid, tv.parent(iid), index)
tv = ttk.Treeview(root, columns=['size','modified'], selectmode=None)
tv.heading('#0', text='Name', command=lambda: sort(tv, '#0'))
tv.heading('size', text='Size', anchor='center', command=lambda: sort(tv, 'size'))
tv.heading('modified', text='Modifies', anchor='center', command=lambda: sort(tv, 'modified'))
tv.column('#0', stretch = True, anchor='w')
tv.column('size', width=100, anchor='center')
tv.column('modified',anchor='center')
tv.grid_rowconfigure(0, weight=1)
tv.grid_columnconfigure(0, weight=1)
tv.grid(row=0, column=0, sticky='nsew')
#tv.pack(expand=True, fill='both')
for path in paths:
meta = path.stat()
parent = str(path.parent)
if parent == '.':
parent = ''
tv.insert(parent, 'end', iid=str(path), text=str(path.name), values=[meta.st_size, meta.st_mtime])
scrollbar = ttk.Scrollbar(root, orient=tk.VERTICAL, command=tv.yview)
tv.configure(yscrollcommand=scrollbar.set)
scrollbar.grid(row=0, column=1, sticky='nse') #scrollbar goes not to the left!
root.mainloop()
As the error said, you cannot use .set()
on column "#0"
(tree column).
Use .item()
instead:
def sort(tv, col):
itemlist = list(tv.get_children(''))
if col == '#0':
itemlist.sort(key=lambda x: tv.item(x, 'text'))
else:
itemlist.sort(key=lambda x: tv.set(x, col))
for index, iid in enumerate(itemlist):
tv.move(iid, tv.parent(iid), index)