質問するログイン新規登録
Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Tkinter

Tkinterは、GUIツールキットである“Tk”をPythonから利用できるようにした標準ライブラリである。

Q&A

解決済

1回答

3897閲覧

python tkinter クリックのみでtreeviewにて複数選択したい

TheBullchannel

総合スコア33

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Tkinter

Tkinterは、GUIツールキットである“Tk”をPythonから利用できるようにした標準ライブラリである。

0グッド

0クリップ

投稿2022/04/02 05:57

0

0

tkinter treeviewでリストボックスに関して、
リスト内のアイテムをクリックするだけで、複数の項目を選択したいです。

ctrlを押しながらクリックすれば、複数の項目を選択できるのですが、
クリックのみでは1項目のみの選択となります。

クリックしたアイテムをリストに追加し、最後に反映させようと下記コードを
書いてみましたが、アイテムの追加と削除のループに陥ります。

問題点・対処法等ご教示ください。
よろしくお願いいたします。

selected_list = []

def event_select(event):

if tree.focus() in selected_list: selected_list.remove(tree.focus()) else: selected_list.append(tree.focus()) tree.selection_set(selected_list)

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

tkinter の複数要素選択は、selectmode で変更可能で、
Listbox では selectmode="multiple" で複数選択可能になりますが、
残念ながら、ttk.Treeview ではサポートされてません。

python

1# デフォルトの振る舞いを変更でも良いなら (全ての treeview の挙動変更) 2root.eval(""" 3 bind Treeview <ButtonPress-1> \ 4 { ttk::treeview::Select %W %x %y toggle } 5""") 6

参考: Control クリックした場合のイベント treeview.tcl Tcl言語のソースコード

デフォルトの振る舞いをキャンセルして、
Ctrlクリックした時と同じ処理を呼び出すようにすれば、実現できると思いますが、
Select メソッドは tkinter のクラスでは提供されてません。
tcl の eval で直接 Tcl のコマンドを呼び出す実装になります。


追記: 質問のコードの問題点について、

ループするというのは、event_select は <<<TreeviewSelect>> での呼び出しでしょうか?
原因はイベントハンドラ内で同イベントが発呼されている為なので、
イベントハンドラ内でそのハンドラのトリガーとなるイベントを起こしてはいけません。

一応、マウスクリック時にフラグを立てる等で、ループしないように工夫することは可能ですが、
他の問題を引き起こしやすいコードになる為、回避策のひとつとして案だけ提示しておきます。あまりお勧めは出来ません。


追記2:

ttk::treeview::Select ~ toggle は select_toggle で代用出来ました。
focus 状態の要素を所得する為、ButtonPress ではなく Release 時に登録。

python

1import tkinter as tk 2from tkinter import ttk 3 4root = tk.Tk() 5tree = ttk.Treeview(root, selectmode="none", columns=("value",)) 6tree.bind("<ButtonRelease-1>", lambda e: tree.select_toggle(tree.focus())) 7 8for num in range(5): 9 tree.insert("", tk.END, values=(num,)) 10 11tree.pack() 12root.mainloop() 13

投稿2022/04/02 07:39

編集2022/04/02 20:43
teamikl

総合スコア8817

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

TheBullchannel

2022/04/02 08:34

ご回答ありがとうございます。 Treeviewselectでの呼び出しです。 常にアイテムが選択されている状態でevent_select()が呼び出されているからループに陥るという認識で正しいでしょうか。 その場合、どのような対策がございますでしょうか。他の方法による実装でも構いません。 ご教示の程、よろしくお願いいたします。
teamikl

2022/04/02 20:02

対策は回答に書いた通りです。少し掘り下げると A案: Control が押されてるときと同じ挙動 ttk::treeview::Select を直接呼び出す B案: ボタンクリック時にフラグを立て、event_select が3回以上呼ばれないようにする。  1回目の呼出で目的の処理・フラグをオフにする。  2回目の呼出は発生してしまうがフラグがオフなら処理をしない A案 は他の方法による実装。B案がループ対策です。
teamikl

2022/04/03 03:57 編集

>常にアイテムが選択されている状態でevent_select()が呼び出されているからループに陥るという認識で正しいでしょうか。 選択解除でも発生するイベントなので、常に選択されているかどうかは関係なく、 event_select 内の selection_set() が TreeviewSelect イベントを発生させます。 変更がなければイベントは発生しませんが、 処理内部の扱いとして同じ選択項目で上書きとなってるようです。 (見た目の選択項目は同じでも、内部では上書きでの変更扱いになる)
teamikl

2022/04/03 03:56

他の実装案2を回答に追記しました。 独自の選択時の挙動を実装したい場合、 selectmode を none に設定で標準の選択挙動を無効にし、 新たにクリック時に選択・選択解除するようなイベントを設定すると良いそうです。 独自の selectmode を実装する方法も試しましたが、 こちらは C言語のソース迄手を入れる必要が出てきたので見送り。
TheBullchannel

2022/04/07 09:13

ありがとうございます。追記2の方法により、実装できました。 selectmode をnoneに設定した場合、選択自体ができなくなると思っていたので、 参考になりました。 selection_set()を実行しなければ、思い通りの動作となっていたのに、selection_set()を実行すると動作がおかしくなるというのは、上書きが発生していたからなのですね。 ご回答いただきありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.30%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問