2017-12-07 25 views
2

私にはttk.Notebookがあり、各タブにはttk.Treeviewが含まれています。すべてのツリービューには同じ列がありますが、下のコードのように異なる項目が含まれています。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() 

私はすべてのツリーが常に同じ列幅を持つようにしたいと思います。たとえば、ユーザーが列「a」のサイズをtree1に変更すると、列「a」のtree2もサイズ変更する必要があります。

私は tree1.column('a', 'width')でカラムのサイズを取得し、tree2.column('a', width=300)と設定することができます。

しかし、どのようにして列のサイズが変更されたことを検出できますか?

ツリービュー<Configure>イベントが列のサイズ変更によってトリガーされないことを確認しました。

+2

あなたがユーザーとの対話のためだけ気にする場合は、 ''バック 'イベントへのコールを結合して、' identify_region(event.x、event.y)を確認することができます。 'separator 'を返す場合、' identify_column(event.x) 'とそれに続く' width'を介してカラムの 'iid'を取得します。指定された幅を持つ指定されたウィジェットのすべての列を反復処理する関数を作成します。あなたが 'width'をプログラム的に変更した場合、その関数を呼び出してください。ユーザーによって変更された場合は、 ''がそれを処理する必要があります。 – CommonSense

+1

ええ、それは良いアイデアのように見えます。しかし、私はどれくらいパフォーマンスが低下するのか、ツリービューがどれくらい反応するかは分かりません。明らかに実装に依存しています。しかし、別のオプションは、同じロジックで ' 'にバインドして、起こりうる性能問題を防ぐことです。 – CommonSense

+0

'ttk :: treeview :: Press'でこれを解決するのは面白いことでしょう。 – Nae

答えて

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

EDIT:私たちは(「区切り」を返さないtree.identify_region(event.x, event.y))早すぎる列セパレータを移動した場合、上記の方法が機能しないことに気づきました。だから私は別の方法を発見した:ユーザーがタブを変更すると、現在のタブの各列の幅は、以前に表示されたタブの対応する列の幅に設定されます。

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() 
関連する問題