如何检测 ttk.Treeview 列的大小调整?

How to detect resizing of ttk.Treeview column?

我有一个 ttk.Notebook,每个选项卡都包含一个 ttk.Treeview。所有树视图都具有相同的列,但包含不同的项目,如以下代码所示。

import tkinter as tk
from tkinter import ttk

root = tk.Tk()

notebook = ttk.Notebook(root)
notebook.pack()

tree1 = ttk.Treeview(notebook, columns=['a', 'b', 'c'])
tree1.insert('', 'end', text='item1', values=('a1', 'b1', 'c1'))
tree2 = ttk.Treeview(notebook, columns=['a', 'b', 'c'])
tree2.insert('', 'end', text='item2', values=('a2', 'b2', 'c2'))
tree2.insert('', 'end', text='item2', values=('a2', 'b2', 'c2'))

notebook.add(tree1, text='Tab 1')
notebook.add(tree2, text='Tab 2')

root.mainloop()

我希望所有树的列宽始终相同。因此,例如,当用户调整 tree1 的 'a' 列大小时,tree2 的 'a' 列也应调整大小时。

我知道我可以用 tree1.column('a', 'width') 并设置为 tree2.column('a', width=300).

但是我如何才能检测到列的大小发生了变化?

我已经检查过 treeview <Configure> 事件不是由列大小调整触发的。

根据 CommonSense 的建议,我对 <ButtonRelease-1> 进行了绑定以检查列的大小是否已调整。如果 tree.identify_region(event.x, event.y)'separator' 则需要调整大小。然后我需要识别分隔符两侧的列。 tree.identify_column(event.x)'#<column number>' 的形式给我左侧​​的列,从中我可以得到右侧列的 ID。 最后,我执行调整所有树中列大小的函数。

import tkinter as tk
from tkinter import ttk

root = tk.Tk()


def on_click_release(event):
    tree = event.widget
    if tree.identify_region(event.x, event.y) == 'separator':
        left_column = tree.identify_column(event.x)
        right_column = '#%i' % (int(tree.identify_column(event.x)[1:]) + 1)
        width_l = tree.column(left_column, 'width')
        width_r = tree.column(right_column, 'width')
        for tree2 in trees:
            if tree2 != tree:
                tree2.column(left_column, width=width_l)
                tree2.column(right_column, width=width_r)


notebook = ttk.Notebook(root)
notebook.pack()

trees = [ttk.Treeview(notebook, columns=['a', 'b', 'c']) for i in range(4)]

for i, tree in enumerate(trees):
    tree.bind('<ButtonRelease-1>', on_click_release)
    notebook.add(tree, text='Tab %i' % i)

root.mainloop()

编辑:我意识到如果我们将列分隔符移动得太快,上述方法将不起作用(tree.identify_region(event.x, event.y) 不会 return 'separator').所以我找到了一个不同的方法:当用户更改选项卡时,则将当前选项卡的每列的宽度设置为先前可见选项卡的相应列的宽度。

import tkinter as tk
from tkinter import ttk


def tab_changed(event):
    global current_tab
    tab = notebook.index('current')  # get newly visible tab number
    tree1 = trees[current_tab]  # get previously visible tree
    tree2 = trees[tab]   # get newly visible tree
    cols = ('#0', ) + tree1.cget('columns')  # tuple of all columns
    for column in cols:
        tree2.column(column, width=tree1.column(column, 'width'))
    current_tab = tab


root = tk.Tk()
notebook = ttk.Notebook(root)
notebook.pack()

trees = [ttk.Treeview(notebook, columns=['a', 'b', 'c']) for i in range(4)]
current_tab = 0  # store currently visible tab number

for i, tree in enumerate(trees):
    notebook.bind('<<NotebookTabChanged>>', tab_changed)
    notebook.add(tree, text='Tab %i' % i)

root.mainloop()