尝试在 tkinter 8.6 Treeview 中使可调整大小的列和可排序的列一起工作

Trying to get resizable columns and sortable columns working together in a tkinter 8.6 Treeview

我运行正在尝试让多个不同的绑定在一棵树上工作时遇到问题。我有所有这些功能独立工作,但当我不希望它们一起激活时,其中一些功能正在激活。[​​=13=]

for col in COLS:
    self.tree.heading(col, text=str(col), command=lambda: self.sortby(col, False))
self.tree.bind("<Button-1>", self.single_click_tree)
self.tree.bind("<Double-1>", self.double_click_tree)

def double_click_tree(self, event):
    region = self.tree.identify( "region", event.x, event.y )
    if region == 'separator':
        self.resize_separator( event )
    elif region == 'cell':
        self.edit_cell( event )

def sortby(self, cid, descending=False):
    data = [(self.tree.set(child, cid), child) for child in self.tree.get_children()]
    data.sort(reverse=descending)
    for i, item in enumerate(data):
        self.tree.move(item[1], '', i)
    self.tree.heading(cid, command=lambda: self.sortby(cid, not descending))

目前,当我尝试通过双击分隔符来调整列的大小时,它会调整它的大小,然后立即对光标悬停在其上的列进行排序。有没有更好的方法可以更好地避免这个问题?正如我所见,我能够解决这个问题的唯一方法是将一个事件传递给 sortby 函数,如果事件坐标在分隔符上但我已经 运行尝试 运行 将新版本的 sortby 函数与事件参数绑定时出现错误:

Exception in Tkinter callback
Traceback (most recent call last):
  File "C:\Users\User\AppData\Local\Programs\Python\Python38\lib\tkinter\__init__.py", line 1892, in __call__
    return self.func(*args)
TypeError: <lambda>() missing 1 required positional argument: 'event'

以及导致此错误的代码:

for col in COLS:
    self.tree.heading(col, text=str(col), command=lambda event: self.sortby(event, col, False))

我能够通过在名为 self.sortable 的 sortby 和调整大小函数中设置一个标志来解决这个问题。双击分隔符以调整列的大小时,sortable 设置为 False,而在释放用于调整大小的鼠标左键单击按钮时,sortable 将设置回 True。 sortby() 仅允许 运行 如果 sortable 为真。

我 运行 遇到了一些时间问题,因为看起来 ButtonRelease-1 绑定到树 运行ning 在 Button-1 列 header 绑定之前,但是这运行在 10 毫秒的 .after() 调用中使用 ButtonRelease-1 函数解决了问题。

我的新代码的相关部分:

self.tree.bind("<Button-1>", self.single_click_tree)
self.tree.bind("<Double-1>", self.double_click_tree)
self.tree.bind("<ButtonRelease-1>",
    lambda event: self.parent.after(10, self.release_tree))

self.resortable = True

def release_tree(self):
    self.resortable = True

def double_click_tree(self, event):
    region = self.tree.identify( "region", event.x, event.y )
    if region == 'separator':
        self.resize_separator( event )
    elif region == 'cell':
        self.edit_cell( event )

def sortby(self, cid, descending=False):
    if not self.resortable:
        return
    
    data = [(self.tree.set(child, cid), child) for child in self.tree.get_children()]
    data.sort(reverse=descending)
    for i, item in enumerate(data):
        self.tree.move(item[1], '', i)
    self.tree.heading(cid, command=lambda: self.sortby(cid, not descending))

def resize_separator(self, event):
    self.resortable = False
    ...