Tkinterチュートリアルシリーズの一環として、本日はTreeViewウィジェットを取り上げます。
TreeViewウィジェットは、アイテムの階層を表示し、すべての属性を並べて表示したい場合に非常に便利です。
例えば、Windowsのファイルエクスプローラのようなアプリケーションを構築したい場合、TkinterのTreeViewウィジェットを使用することができます。
import tkinter.tk as ttk
|
つまり、TreeViewでできることは、ツリー状の構造を構築し、それに沿ってアイテムを属性とともに挿入することです。
ツリーへのノードの追加や削除を動的に行うことができるので、多くのGUIアプリケーションで非常に有用です。
好みに応じてTreeを構成することができる。
ファイルエクスプローラを再現したい場合は、ファイルとその属性のTreeViewを作成し、ネストしたファイルとフォルダを親フォルダの子として追加することになります。
この演習は行いませんが、自分で試してみて、TreeViewがどのように動作するかをよく理解することをお勧めします。
それでは、TreeViewウィジェットをどのように構築し、挿入や削除などの操作を行うか見ていきましょう。
この記事もチェック:PythonでTkinterを使ってGUIの電卓アプリを作成する方法
TreeView Widget の構築
TreeView ウィジェットは tkinter.ttk モジュールに属しているので、これをインポートする必要があります。
tree = ttk.Treeview(master, columns)
|
これで、ウィジェットを ttk.TreeView() として参照できるようになりました。
新しい TreeView ウィジェットを作成するためのシンタックスは簡単です。
tree = ttk.Treeview(master, columns=("Name", "ID"))
|
ここで、tree は新しく作成される木のルートノードに相当します。
ここで、master は Tkinter アプリケーションのメインマスターノードを指します。
columns` はタプルであり、カラムの名前を参照します。
例えば、“Name” と “ID” というカラムを持つ TreeView ウィジェットはこのように構成することができます。
master = tk.Tk()
|
このツリーは、ベースウィジェットとして master を使用して構築されます。
通常、このウィジェットはアプリケーションのメインマスターオブジェクトとして使用されます。
"Label" , "Hello", "Second Col", "Third Col"
|
さて、TreeView ウィジェットができましたが、これは空っぽなので表示する意味がありません。
まずは、実際のアプリケーションでTreeViewを表示するために、いくつかのオブジェクトを挿入してみましょう。
TreeViewのノードの行は、このように文字列だけで構成されていることを覚えておいてください。
tree.insert(parent, index, iid, text, values) |
では、新しく作成したTreeViewにノードを挿入してみましょう。
TreeViewに挿入する
挿入の構文は非常にシンプルです。
TreeViewオブジェクトを取得し、textでラベリングした value を挿入します。
また、 iid パラメータを使用して、ノードのユニークな ID を指定することができます。
tree.insert(parent='', index='end', iid=0, text="Label", values=("Hello", "Second Col", "Third Col"))
|
ここでは、 parent にノードを挿入しています。
もし、 parent ウィジェットをマスター (ルート) ノードにしたい場合は、空文字列 (“) を設定します。
そうでない場合は、既存の親ノードの iid を指定する必要があります。
このノードの子ノードの番号は、 index を使って参照します。
例えば、最初の子ノードに挿入したい場合は、 index=0 を指定します。
また、末尾に挿入したい場合は、特別な値 'end' を指定することができる。
"Label" , "Hello", "Second Col", "Third Col"
|
上記は、ルートノードの末尾に挿入する例であり、値は以下の行のようになる。
import tkinter as tk
import tkinter.ttk as ttk
class Application(tk.Frame):
def __init__(self, root):
self.root = root
self.initialize_user_interface()
def initialize_user_interface(self):
# Configure the root object for the Application
self.root.title("Application")
self.root.grid_rowconfigure(0, weight=1)
self.root.grid_columnconfigure(0, weight=1)
self.root.config(background="green")
# Define the different GUI widgets
self.name_label = tk.Label(self.root, text="Name:")
self.name_entry = tk.Entry(self.root)
self.name_label.grid(row=0, column=0, sticky=tk.W)
self.name_entry.grid(row=0, column=1)
self.idnumber_label = tk.Label(self.root, text="ID")
self.idnumber_entry = tk.Entry(self.root)
self.idnumber_label.grid(row=1, column=0, sticky=tk.W)
self.idnumber_entry.grid(row=1, column=1)
self.submit_button = tk.Button(self.root, text="Insert", command=self.insert_data)
self.submit_button.grid(row=2, column=1, sticky=tk.W)
self.exit_button = tk.Button(self.root, text="Exit", command=self.root.quit)
self.exit_button.grid(row=0, column=3)
# Set the treeview
self.tree = ttk.Treeview(self.root, columns=('Name', 'ID'))
# Set the heading (Attribute Names)
self.tree.heading('#0', text='Item')
self.tree.heading('#1', text='Name')
self.tree.heading('#2', text='ID')
# Specify attributes of the columns (We want to stretch it!)
self.tree.column('#0', stretch=tk.YES)
self.tree.column('#1', stretch=tk.YES)
self.tree.column('#2', stretch=tk.YES)
self.tree.grid(row=4, columnspan=4, sticky='nsew')
self.treeview = self.tree
self.id = 0
self.iid = 0
def insert_data(self):
self.treeview.insert('', 'end', iid=self.iid, text="Item_" + str(self.id),
values=("Name: " + self.name_entry.get(),
self.idnumber_entry.get()))
self.iid = self.iid + 1
self.id = self.id + 1
app = Application(tk.Tk())
app.root.mainloop() |
残念ながら、TreeViewを簡単に構築する方法はありません。
なぜなら、出力を適切に視覚化するためには、他のウィジェットが必要だからです。
この先に進む前に、Tkinter Button、Grid Manager、Tkinter Entryウィジェットに関するチュートリアルのセクションを読んでおいてください。
これらのウィジェットを使って出力を視覚化するサンプルアプリケーションを提供します。
tree.delete(iid) |
ここでは、入力のためのラベルとエントリを作成しました。
また、2つの部分からなるTreeViewを作成しました。
- TreeView Headings (カラム名を表示する)
- TreeViewのカラムと
insert_data()メソッド
Insert “ボタンを押すと、TreeViewウィジェット上でinsert_data()メソッドが呼び出されます。
さて、話はここまでです。
それでは、挿入のテストをしてみましょう。
def delete_data(self):
row_id = int(self.tree.focus())
self.treeview.delete(row_id)
|
さて、うまくいきそうですね。
では、選択した行を削除するために Delete ボタンを追加してみましょう。
この記事もチェック:PythonのTkinterでボタンの状態を取得、有効・無効の切り替えを実装する
TreeViewから行を削除する
TreeView.delete()`メソッドが存在するので、これを利用します。
これは、TreeViewウィジェットから対応するノード(この例では、行)を削除します。
import tkinter as tk
import tkinter.ttk as ttk
class Application(tk.Frame):
def __init__(self, root):
self.root = root
self.initialize_user_interface()
def initialize_user_interface(self):
# Configure the root object for the Application
self.root.title("Application")
self.root.grid_rowconfigure(0, weight=1)
self.root.grid_columnconfigure(0, weight=1)
self.root.config(background="green")
# Define the different GUI widgets
self.name_label = tk.Label(self.root, text="Name:")
self.name_entry = tk.Entry(self.root)
self.name_label.grid(row=0, column=0, sticky=tk.W)
self.name_entry.grid(row=0, column=1)
self.idnumber_label = tk.Label(self.root, text="ID:")
self.idnumber_entry = tk.Entry(self.root)
self.idnumber_label.grid(row=1, column=0, sticky=tk.W)
self.idnumber_entry.grid(row=1, column=1)
self.submit_button = tk.Button(self.root, text="Insert", command=self.insert_data)
self.submit_button.grid(row=2, column=1, sticky=tk.W)
self.delete_button = tk.Button(self.root, text="Delete", command=self.delete_data)
self.delete_button.grid(row=100, column=100)
self.exit_button = tk.Button(self.root, text="Exit", command=self.root.quit)
self.exit_button.grid(row=0, column=3)
# Set the treeview
self.tree = ttk.Treeview(self.root, columns=('Name', 'ID'))
# Set the heading (Attribute Names)
self.tree.heading('#0', text='Item')
self.tree.heading('#1', text='Name')
self.tree.heading('#2', text='ID')
# Specify attributes of the columns (We want to stretch it!)
self.tree.column('#0', stretch=tk.YES)
self.tree.column('#1', stretch=tk.YES)
self.tree.column('#2', stretch=tk.YES)
self.tree.grid(row=4, columnspan=4, sticky='nsew')
self.treeview = self.tree
self.id = 0
self.iid = 0
def insert_data(self):
self.treeview.insert('', 'end', iid=self.iid, text="Item_" + str(self.id),
values=("Name: " + self.name_entry.get(),
self.idnumber_entry.get()))
self.iid = self.iid + 1
self.id = self.id + 1
def delete_data(self):
row_id = int(self.tree.focus())
self.treeview.delete(row_id)
app = Application(tk.Tk())
app.root.mainloop() |
これは単純にノードの識別番号 iid を受け取り、TreeView から削除します。
これを delete_data() というメソッドにまとめます。
さて、大きな疑問は、TreeViewウィジェットからどうやって行のID番号を取得するかということです。
これは、削除操作をどのように実行するかによります。
マウスで行を選択するたびに、その行を削除します。
行がハイライトされた後、削除ボタンを押すと、TreeViewウィジェットからその行が削除されます。
これを行うには、 TreeView.focus() メソッドを使用して、行の iid を(文字列として)取得することになります。
これを利用して、その行を直接削除することができます。
def update(self):
for idx, node in enumerate(self.treeview.get_children()):
self.tree.item(node, text="Updated_Item_" + str(idx))
|
削除ボタンを追加して、このメソッドをコールバック関数として使ってみましょう。
これを追加すると、アプリケーションは次のようになります。

結果は以下の通りです。

これで、TreeViewの基本的な構造が完成しました。
また、基本的な挿入と削除の操作も実装できました。
このアプリケーションでは、行の更新など他の操作を行うことで、より機能的にすることをお勧めします。
また、削除後に項目番号が正しく並ばないことにお気づきかもしれません。
以下に update() のシンプルなテンプレート関数を示しますので、参考にしてください。

これは TreeView のすべての行を更新し、text ラベルを変更します。
他の属性も同様に変更することができます。
これらは、あなたのアプリケーションに加えることができる様々な改良点の一つです。
まとめ
これで TreeView を使った簡単なアプリケーションを動作させることができましたね。
このウィジェットを使って、アプリケーションの行と列をツリー構造で表示する方法を簡単に説明しました。