С помощью параметра command метода heading()
можно привязать к заголовку некоторую функцию, которая будет вызываться по нажатию на заголовок.
treeview.heading(имя_заголовка, command=функция)
Рассмотрим на примере сортировки:
from tkinter import * from tkinter import ttk root = Tk() root.title("METANIT.COM") root.geometry("250x200") # определяем данные для отображения people = [("Tom", 38, "tom@email.com"), ("Bob", 42, "bob@email.com"), ("Sam", 28, "sam@email.com")] # определяем столбцы columns = ("name", "age", "email") tree = ttk.Treeview(columns=columns, show="headings") tree.pack(expand=1, fill=BOTH) def sort(col, reverse): # получаем все значения столбцов в виде отдельного списка l = [(tree.set(k, col), k) for k in tree.get_children("")] # сортируем список l.sort(reverse=reverse) # переупорядочиваем значения в отсортированном порядке for index, (_, k) in enumerate(l): tree.move(k, "", index) # в следующий раз выполняем сортировку в обратном порядке tree.heading(col, command=lambda: sort(col, not reverse)) # определяем заголовки tree.heading("name", text="Имя", anchor=W, command=lambda: sort(0, False)) tree.heading("age", text="Возраст", anchor=W, command=lambda: sort(1, False)) tree.heading("email", text="Email", anchor=W, command=lambda: sort(2, False)) tree.column("#1", stretch=NO, width=70) tree.column("#2", stretch=NO, width=60) tree.column("#3", stretch=NO, width=100) # добавляем данные for person in people: tree.insert("", END, values=person) root.mainloop()
Как и в предыдущих примерах, виджет Treeview использует список кортежей people и представляет таблицу с тремя столбцами.
Для сортировки определена функция sort()
, которая принимает два параметра: col(номер столбца, по которому идет сортировка) и reverse (направление сортировки - по возрастанию или убыванию)
def sort(col, reverse):
Рассмотрим действие функции по этапно:
При добавлениии элементов в Treeview каждому из них присваивается идентификатор. Используя идентификатор, можно получить все значения элемента в Treeview. Это необходимо, чтобы отсортировать элементы:
l = [(tree.set(k, col), k) for k in tree.get_children("")]
Здесь вначале пробегаемся по всем элементам в Treeview с помощью метода tree.get_children("")
. В метод передается пустая строка "", поскольку мы хотим получить
элементы верхнего уровня (по сути строки таблицы). Соответственно переменная k здесь будет представлять идентификатор элемента
Для каждого элемента с помощью метода set получаем с помощью идентификатора значение столбца строки:
tree.set(k, col)
Например, если col=0 (то есть сортировка идет по имени, то вызов tree.set(k, col)
возвращает имя ("Tom", "Bob", "Sam").
Полученное значение помещаем в кортеж:
(tree.set(k, col), k)
Из кортежей формируется список:
l = [(tree.set(k, col), k) for k in tree.get_children("")]
То есть если, к примеру, сортировка идет по имени, то на выходе переменная l будет представлять список кортежей типа [("Tom", "I001"), ("Bob", "I002"), ("Sam", "I003")]
Затем сортируем список с помощью встроенной метода sort()
:
l.sort(reverse=reverse)
В методе указываем направление сортировки с помощью параметра reverse
Список отсортирован, но на отображение данных в таблице это пока никак не повлияло. Нам надо переупорядочить строки, привести их в соответствие с отсортированным списком l. Для этого переставляем их с помощью метода move()
:
for index, (_, k) in enumerate(l): tree.move(k, "", index)
Сначала с помощью функции enumerate()
из списка l получаем набор объектов, который состоит из индекса и собственно данных. При переборе этого набора индекс получаем в переменную index,
а набор данных в кортеж (_, k)
- первый элемент кортежа представляет имя, но здесь оно нам уже не нужно, оно использовалось на предыдущем шаге для сортировки.
А второй элемент кортежа - идентификатор строки.
В цикле с помощью вызова tree.move(k, "", index)
перемещаем элемент с идентификатором k, который является элементов верхнего уровня (второй аргумент - "") на позицию с индексом index.
На финальной стадии переустанавливаем определение заголовка:
tree.heading(col, command=lambda: sort(col, not reverse))
Параметр command
в качестве выполняемой функции получает лямбда-выражение, которое вызывает функцию sort. При этом функции передается противоположное направление сортировки.
Благодаря этому при следующем нажатии на заголовок сортировка будет идти в противоположном направлении.
Результат работы программы: