代码之家  ›  专栏  ›  技术社区  ›  Paul-ET

对树状图应用程序发送的第一列进行排序失败

  •  0
  • Paul-ET  · 技术社区  · 11 月前

    我使用教程中的一个示例对树视图中的列进行排序。它适用于第2列和第3列,但不适用于第1列。如果我点击标题,我会得到这个错误:

    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
    

    我有这个小测试程序作为参考,但找不到故障。我感谢任何解决这个问题的提示,或者根本不可能对第一列进行排序,因为它是一棵树?

    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()
    
    1 回复  |  直到 11 月前
        1
  •  1
  •   acw1668    11 月前

    正如错误所说,你不能使用 .set() 在列 "#0" (树柱)。

    使用 .item() 相反:

    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)