【问题标题】:How to detect resizing of ttk.Treeview column?如何检测 ttk.Treeview 列的大小调整?
【发布时间】:2017-12-07 12:40:59
【问题描述】:

我有一个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> 事件不是由调整列大小触发的。

【问题讨论】:

  • 如果您只关心用户交互,您可以将回调绑定到<B1-Motion> 事件并检查identify_region(event.x, event.y)。如果它返回'separator' - 之后通过identify_column(event.x)width 获取列的iid。创建一个函数,它将遍历具有指定宽度的指定小部件的所有列。如果您以编程方式更改width - 只需调用该函数。如果它通过用户更改 - <B1-Motion> 应该处理它。
  • 是的,这看起来是个好主意。但是,我不知道它对性能的影响有多大,以及treeview 的响应速度如何,显然这取决于实现。但是,另一种选择是使用相同的逻辑绑定到 <ButtonRelease-1>,以防止可能的性能问题。
  • ttk::treeview::Press 解决这个问题可能会很有趣。

标签: python tkinter ttk


【解决方案1】:

根据 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) 不返回“分隔符”)。于是我找到了一种不同的方法:当用户改变tab时,那么将当前tab的每一列的宽度设置为之前可见的tab对应列的宽度。

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()

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-05-09
    • 1970-01-01
    • 2011-12-26
    • 2021-12-08
    • 1970-01-01
    • 1970-01-01
    • 2013-02-10
    相关资源
    最近更新 更多