1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

SuiSuiAdvent Calendar 2023

Day 24

Treeviewで項目ごとにデータをソートする

Posted at

はじめに

tkinterのTreeviewを使用すると,データを表形式のGUIで表示することが可能です.ただ,これらのデータは追加した順に表示されます.
今回はヘッダーをクリックすることで,項目ごとにデータをソートする機能を追加した際の備忘録です.

動作環境

  • Python 3.12.0
  • tkinter 8.6.12

ソースコード

sample.py
import tkinter as tk
from tkinter import ttk

def select_header(tree, reverse_flag):
    # クリックされたヘッダー列取得
    x = tree.winfo_pointerx() - tree.winfo_rootx()
    select_column_str = tree.identify_column(x)
    select_column_int = int(select_column_str[1:]) - 1

    l = [(tree.set(k, select_column_int), k) for k in tree.get_children("")]
    l.sort(reverse=reverse_flag)

    for index, (val, k) in enumerate(l):
        tree.move(k, "", index)

    tree.heading(select_column_int, command=lambda:select_header(tree, not reverse_flag))

main = tk.Tk()

style = ttk.Style()
style.theme_use("clam")

datas = [
    ["1", "4", "b"],
    ["2", "3", "d"],
    ["3", "2", "a"],
    ["4", "1", "c"],
]

columns = 0
for data in datas:
    if columns < len(data):
        columns = len(data)
clmn = tuple(range(columns))

tree = ttk.Treeview(main, columns=clmn, show="headings")
tree.grid(row=0, column=0, sticky="nsew")

for i in range(columns):
    tree.heading(i, text="Data"+str(i+1), command=lambda:select_header(tree, False))
for data in datas:
    tree.insert("", "end", value=(data))

main.mainloop()

クリックしたヘッダー列取得

「どの列をソートするか」を判別するために,クリックしたヘッダーを識別します.

x = tree.winfo_pointerx() - tree.winfo_rootx()
select_column_str = tree.identify_column(x)
select_column_int = int(select_column_str[1:]) - 1

画面に表示しているx座標をもとにidentify_column()でヘッダ名を#~の形で特定します.select_column_intの値は左のヘッダーから順に0,1,2...となります.

データをソート

l = [(tree.set(k, select_column_int), k) for k in tree.get_children("")]
l.sort(reverse=reverse_flag)

get_childran()でクリックしたヘッダー列のデータのリストを取得します.sort()で取得したデータをソートします.オプションのreverseは,Trueが降順ソート,Falseが昇順ソートとなります.

Treeviewにデータをソート順に表示

for index, (val, k) in enumerate(l):
    tree.move(k, "", index)

Treeviewのmoveメソッドはkindexの位置に移動させます.

今回のソースコードでは,関数内のheadingselect_header(tree, not revers_flag)を設定することで,クリックするごとに昇順ソート,降順ソートを繰り返すようになっています.

おわりに

Treeviewでソートは基本装備していい気がするので便利なメソッドがあればいいなと切実に思いました.

参考文献

1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?