初心者でもPythonを使ってみよう

趣味と実益を兼ねたPython学習記



【tkinter.ttk】 Treeviewの使い方 【Python】

tkinter.ttkで利用できるTreeviewの使い方を、実際にコードを書きながらまとめました。

【スポンサーリンク】

階層構造を持つアイテムツリーの表示

動作内容

ツリービューは、階層構造を持つアイテムツリー表示するためのウィジェットで、あるフォルダ内のファイル構成の可視化に使用されることが多いです。

以下の様な階層構造を持つ辞書型のアイテムをツリービューで階層表示してみます。

menu = {
    "Food":["Hamburger", "Beef steak", "Salad"],
    "Softdrink":["Coke", "Cider", "Tea"],
    "Alcohol":["Beer", "Wine", "Cocktail"],
    }

以下がツリービューで表示した結果です。

f:id:vigilantPotato:20190525155009p:plain

辞書のキーである「Food」、「Softdrink」、「Alcohol」が表示されており、文字横の「+」をクリックすると、それぞれのキーに対するバリューが表示されます。

f:id:vigilantPotato:20190525155112p:plain

階層構造を持つ辞書型アイテムを、ツリービューで階層表示することができました。

[↑ 目次へ]

コードの説明

準備

まずはモジュールのインポートし、tkinterのトップレベルウィジェットを作成します。

インポートするモジュールはtkinterとtkinter.ttkです。

import tkinter
from tkinter import ttk

#1. 辞書表示用ツリービュークラス

if __name__ == "__main__":
    root = tkinter.Tk()

    #2.ツリービューの表示
    
    root.mainloop()

1.階層構造表示用ツリービュークラス

次に、辞書型の階層構造を表示するためのツリービュークラスを作成します。

ttk.Treeviewクラスを継承させ、クラス名をTestTreeviewとしました。

class TestTreeview(ttk.Treeview):
    def __init__(self, master=None):
        super().__init__(master=master)
        menu = {
            "Food":["Hamburger", "Beef steak", "Salad"],
            "Softdrink":["Coke", "Cider", "Tea"],
            "Alcohol":["Beer", "Wine", "Cocktail"],
            }
        
        #辞書のキーを挿入
        for p in menu:
            root_node = self.insert(
                "",     #最上位なのでparentは空文字
                "end",
                text=p,
                )
            #辞書の要素を挿入    
            for m in menu[p]:
                self.insert(
                    root_node,  #parentはキーの認識番号
                    "end",
                    text=m,
                    )

2重のfor文でmenu内のキーとバリューをツリービューへ挿入していっています。

ツリービューへの挿入にはinsertメソッドを使用します。親要素を挿入する際に、insertメソッドの引数に空文字、挿入する位置、表示するテキストを渡しています。

子要素を挿入する際には、insertメソッドの一つ目の引数を親要素挿入時の戻り値(上記の例では変数root_node)としています。こうすることで、階層表示が可能になります。

2.ツリービューの表示

最後に、「TestTreeview」を生成して完成です。

#2.ツリービューの表示
t = TestTreeview(master=root)
t.pack()

[↑ 目次へ]

コード全体

import tkinter
from tkinter import ttk

#1. 辞書表示用ツリービュークラス
class TestTreeview(ttk.Treeview):
    def __init__(self, master=None):
        super().__init__(master=master)
        menu = {
            "Food":["Hamburger", "Beef steak", "Salad"],
            "Softdrink":["Coke", "Cider", "Tea"],
            "Alcohol":["Beer", "Wine", "Cocktail"],
            }
        
        #辞書のキーを挿入
        for p in menu:
            root_node = self.insert(
                "",     #最上位なのでparentは空文字
                "end",
                text=p,
                )
            #辞書の要素を挿入    
            for m in menu[p]:
                self.insert(
                    root_node,  #parentはキーの認識番号
                    "end",
                    text=m,
                    )


if __name__ == "__main__":
    root = tkinter.Tk()

    #2.ツリービューの表示
    t = TestTreeview(master=root)
    t.pack()
    
    root.mainloop()

[↑ 目次へ]

【スポンサーリンク】

フォルダ・ファイル構成をツリービューで表示

動作内容

応用として、Treeviewを用いて以下の2つの機能を持つアプリを作成していきます。

  1. カレントディレクト内のファイル名、サブフォルダ名をリスト化して表示する。
  2. リスト化された項目をクリックすると、そのファイル名と親フォルダ名を取得してラベルに表示する。

完成したアプリの起動時の画面を以下に示します。 上から、選択したアイテム表示用のラベルと、その親アイテムの表示用のラベル、ツリービューが表示されています。

f:id:vigilantPotato:20190525155520p:plain

ツリービュー内のアイテムをクリックすると、上部のラベルにアイテム名を取得して表示します。

今回の例では、カレントディレクトリ内のファイルは最上位の要素になるため、親アイテム名は空文字になります。

f:id:vigilantPotato:20190525155607p:plain

[↑ 目次へ]

コードの説明

準備

tkinter、tkinter.ttkと、パスの操作用にosモジュールをインポートし、トップレベルウィジェットを生成します。

import tkinter
from tkinter import ttk
import os

#1. ファイル構造表示用ツリービュークラス

if __name__ == "__main__":
    root = tkinter.Tk()

    #2. ツリービューの表示

    root.mainloop()

1.ファイル構造表示用ツリービュークラス

次に、ファイル構造表示用のツリービュークラスを生成します。名前はFileTreeviewとして、ttk.Treeviewを継承させます。

#1. ファイル構造表示用ツリービュークラス
class FileTreeview(ttk.Treeview):
    def __init__(self, master=None):
        super().__init__(master)
        self.process_directory("", os.getcwd())
        self.bind("<<TreeviewSelect>>", self.show_selected)

        #選択アイテム表示用ラベル
        self.filename = tkinter.Label(
            master=None,
            text="Filename",
            bg="lightblue",
            width=15,
            )
        self.filename.pack()

        #親アイテム表示用ラベル
        self.foldername = tkinter.Label(
            master=master,
            text="Folder",
            bg="lightgreen",
            width=15,
            )
        self.foldername.pack()

    def process_directory(self, parent, path):
        for p in os.listdir(path):
            abspath = os.path.join(path, p)
            oid = self.insert(
                parent,
                "end",
                text=p,
                )
            if os.path.isdir(abspath):
                self.process_directory(oid, abspath)

    def show_selected(self, event):
        curItem = self.focus()              #選択アイテムの認識番号取得
        parentItem = self.parent(curItem)   #親アイテムの認識番号取得
        self.filename["text"] = self.item(curItem)["text"]
        self.foldername["text"] = self.item(parentItem)["text"]

FileTreeviewクラスの各メソッドの説明は以下の通りです。

  1. init

    • カレントディレクト内のファイル・フォルダを取得するprocess_directoryメソッドを実行。
    • アイテムクリック時に発生するTreeviewSelectイベントを用いて、アイテムクリック時にshow_selectedメソッドを実行するように設定。
    • アイテム表示用ラベルの生成
  2. process_directory(self, parent, path)

    • parent:親アイテムの認識番号
    • path:リスト化するフォルダのパス
    • path内のファイル、フォルダをツリービューへ追加(insert)する。
    • フォルダを追加した際は、そのフォルダの認識番号を引数として自分自身を呼び出し(再帰呼び出し)、フォルダ内のファイルもツリービューへ挿入する。
  3. show_selected(self, event)

    • アイテム選択時に発生するTreeviewSelectイベントで実行。
    • 選択したアイテムの認識番号を取得し、テキストとその親要素のテキストをラベルに表示する。

2.ツリービューの表示

最後に、「FileTreeview」を生成して完成です。

#2.ツリービューの表示
t = FileTreeview(master=root)
t.pack()

[↑ 目次へ]

コード全体

import tkinter
from tkinter import ttk
import os

#1. ファイル構造表示用ツリービュークラス
class FileTreeview(ttk.Treeview):
    def __init__(self, master=None):
        super().__init__(master)
        self.process_directory("", os.getcwd())
        self.bind("<<TreeviewSelect>>", self.show_selected)

        #選択アイテム表示用ラベル
        self.filename = tkinter.Label(
            master=None,
            text="Filename",
            bg="lightblue",
            width=15,
            )
        self.filename.pack()

        #親アイテム表示用ラベル
        self.foldername = tkinter.Label(
            master=master,
            text="Folder",
            bg="lightgreen",
            width=15,
            )
        self.foldername.pack()

    def process_directory(self, parent, path):
        for p in os.listdir(path):
            abspath = os.path.join(path, p)
            oid = self.insert(
                parent,
                "end",
                text=p,
                )
            if os.path.isdir(abspath):
                self.process_directory(oid, abspath)

    def show_selected(self, event):
        curItem = self.focus()              #選択アイテムの認識番号取得
        parentItem = self.parent(curItem)   #親アイテムの認識番号取得
        self.filename["text"] = self.item(curItem)["text"]
        self.foldername["text"] = self.item(parentItem)["text"]


if __name__ == "__main__":
    root = tkinter.Tk()

    #2.ツリービューの表示
    f = FileTreeview(master=root)
    f.pack()
    root.mainloop()

[↑ 目次へ]