【Python】tkinter.ttk.Treeview:テーブル(表)で選択された行を判別・取得・削除(bind)

2021.10.27 /

【Python】tkinter.ttk.Treeview:テーブル(表)で選択された行を判別・取得・削除(bind)

本記事ではPythonのtkinterにおける、テーブル(表)の行が選択されたときに、その行(レコード)の情報を判別・取得・削除する方法について解説していきます。

GUIアプリケーションでテーブル内のレコードがクリックされたら、なにかしらの操作を行うことが多いです。

その操作を行うためには、選択された行を判別する必要があります。
選択された行を判別したら、そこから情報の取得や削除といった操作を行います。

これらの方法について、本記事では詳しく解説していきます。

tkinterのTreeviewウィジェットでテーブル(表)を作成する方法については以下記事をご参照ください。

基本的なTkinterの操作方法については以下記事をご参照ください。

テーブルのイベントと関数を紐づける(bindメソッド)

そもそもテーブルがクリックされたときに、どのような流れでクリックされた行を判別するのでしょうか。

それは以下の流れで行っていきます。

  1. テーブル内のレコードがクリックされる
  2. テーブルに指定したクリックイベントに対する関数を実行する
  3. 関数内でクリックされた行を判別する

まず設定すべきこととして上記の流れでいうと、2番のテーブルがクリックされたイベントと関数を紐づける必要があります。

特定のウィジェットのイベント発生と関数を紐づけるためにはbind()メソッドを利用します。

bind()メソッドはすべてのウィジェットに対してトリガーとなる特定のイベントと実行する関数(コールバック関数)の紐づけを行うことができます。

bind()メソッドの使い方に関しては以下記事をご参照ください。

bind()メソッドの構文は次のようになります。

構文

widget.bing(event, def)

引数eventにはトリガーとなるイベント(操作)を指定し、引数defにはコールバック関数を指定します。

Treeviewウィジェットに用意されているイベントは次の3つがあります。

イベント 説明
<<TreeviewSelect>> アイテム(行)が選択時に発生
<<TreeviewOpen>> フォーカスのある階層列が開く前に発生
<<TreeviewClose>> フォーカスのある階層列が閉じた後に発生

テーブル操作では<<TreeviewSelect>>を主に利用します。

テーブルの選択された行から情報を取得

次のサンプルコードを使って、テーブルが選択されたときの行の情報を取得する方法を解説していきます。

下記サンプルプログラムは、行をクリックするとクリックした行の情報がメッセージボックスに表示するものです。

# サンプルコード
import tkinter as tk
from tkinter import ttk

def select_record(event):
    # 選択行の判別
    record_id = tree.focus()
    # 選択行のレコードを取得
    record_values = tree.item(record_id, 'values')
    if tk.messagebox.showinfo(title="選択行の確認",
                              message="次の行が選択されました=> id:"
                              + record_values[0]
                              + ",Name:" + record_values[1]
                              + ",Score:" + record_values[2]):
        tree.delete(record_id)
    else:
        pass

# 列の識別名を指定
column = ('ID', 'Name', 'Score')
# メインウィンドウの生成
root = tk.Tk()
root.title('Score List')
root.geometry('400x300')
# Treeviewの生成
tree = ttk.Treeview(root, columns=column)
tree.bind("<<TreeviewSelect>>", select_record)
# 列の設定
tree.column('#0',width=0, stretch='no')
tree.column('ID', anchor='center', width=80)
tree.column('Name',anchor='w', width=100)
tree.column('Score', anchor='center', width=80)
# 列の見出し設定
tree.heading('#0',text='')
tree.heading('ID', text='ID',anchor='center')
tree.heading('Name', text='Name', anchor='w')
tree.heading('Score',text='Score', anchor='center')
# レコードの追加
tree.insert(parent='', index='end', iid=0 ,values=(1, 'KAWASAKI',80))
tree.insert(parent='', index='end', iid=1 ,values=(2,'SHIMIZU', 90))
tree.insert(parent='', index='end', iid=2, values=(3,'TANAKA', 45))
tree.insert(parent='', index='end', iid=3, values=(4,'OKABE', 60))
tree.insert(parent='', index='end', iid=4, values=(5,'MIYAZAKI', 99))
# ウィジェットの配置
tree.pack(pady=10)

root.mainloop()
tkinter:テーブルの選択された行から情報を取得

イベントと関数の紐づけ:bind()メソッド

Treeviewオブジェクトに対してbind()メソッドで次のようにして、関数を紐づけています。

tree.bind("<<TreeviewSelect>>", select_record)

イベントは<<TreeviewSelect>>なので、テーブル内のレコードが選択されたときに、紐づいている関数select_recordが実行されます。

選択された行の判別:focus()メソッド

関数select_record内では、まず選択された行の判別を行っています。

選択された行の判別に利用するメソッドとしては次の2つが用意されています。

  • focus()メソッド
  • selection()メソッド

selection()メソッドでは、選択された行のアイテムをタプルで返します。
focus()メソッドでは、フォーカスがある行のアイテムIDを返します。

サンプルコードではfocus()メソッドを利用して、選択された行のアイテムIDを取得しています。

record_id = tree.focus()

これらメソッドを利用することで、選択された行を判別しております。

選択された行から情報の取得:item()メソッド

次に選択された行から情報を取得するために、item()メソッドを使用します。

item()メソッドでは、指定したアイテム(レコード)のオプション値を設定または取得ができます。

構文

item(item, option=None, **kw)

引数itemにはアイテムIDを指定します。
引数kwには取得したいオプション名を指定します。引数kwを省略すると、全オプション値を取得します。

サンプルコードではオプション名valuesを指定し、レコードの値をすべて取得しています。

record_values = tree.item(record_id, 'values')

取得したレコード値はタプル型なので、一つ一つを取り出すためにインデックスによる要素の指定を行います。

record_values[0], record_values[1]

ここまで解説した方法を利用して、選択した行から値を取得することができます。

選択された行を削除

ここでは選択された行を削除するスクリプトを紹介いたします。

次のサンプルコードでは行が選択されると、メッセージボックスで削除するかを尋ねます。「OK」を押すと、選択した行が削除されます。

# サンプルコード
import tkinter as tk
from tkinter import ttk

def delete_record(event):
    record_id = tree.focus()
    record_values = tree.item(record_id, 'values')
    if tk.messagebox.askokcancel(title="削除の確認", message="選択したレコードを削除しますか?"):
        tree.delete(record_id)
    else:
        pass

# 列の識別名を指定
column = ('ID', 'Name', 'Score')
# メインウィンドウの生成
root = tk.Tk()
root.title('Score List')
root.geometry('400x300')
# Treeviewの生成
tree = ttk.Treeview(root, columns=column)
tree.bind("<<TreeviewSelect>>", delete_record)
# 列の設定
tree.column('#0',width=0, stretch='no')
tree.column('ID', anchor='center', width=80)
tree.column('Name',anchor='w', width=100)
tree.column('Score', anchor='center', width=80)
# 列の見出し設定
tree.heading('#0',text='')
tree.heading('ID', text='ID',anchor='center')
tree.heading('Name', text='Name', anchor='w')
tree.heading('Score',text='Score', anchor='center')
# レコードの追加
tree.insert(parent='', index='end', iid=0 ,values=(1, 'KAWASAKI',80))
tree.insert(parent='', index='end', iid=1 ,values=(2,'SHIMIZU', 90))
tree.insert(parent='', index='end', iid=2, values=(3,'TANAKA', 45))
tree.insert(parent='', index='end', iid=3, values=(4,'OKABE', 60))
tree.insert(parent='', index='end', iid=4, values=(5,'MIYAZAKI', 99))
# ウィジェットの配置
tree.pack(pady=10)

root.mainloop()
tkinter:テーブルで選択された行を削除

行を削除:delete()メソッド

選択された行を削除するためにdelete()メソッドを使用します。

構文

delete(items)

引数itemsにはアイテムIDを指定します。アイテムIDは複数指定可能です。

delete()メソッドで削除したアイテムは復元することができませんので、復元をする可能性がある場合は、detach()メソッドを利用してください。

まとめ

本記事「【Python】tkinter.ttk.Treeview:テーブル(表)で選択された行を判別・取得・削除(bind)」はいかがでしたか。

ぜひTkinterでテーブルを作成して、データベースとうまく連携するアプリケーションを作成してみてください。