Реализация таблиц в интерфейсе Tkinter на Python

Раздел: GUI -> Tkinter

Основное решение: ttk.Treeview

ttk.Treeview является стандартным компонентом Tkinter для отображения иерархических и табличных данных. Он поддерживает столбцы, заголовки, выбор строк, теги, вложенные элементы. Это наиболее гибкое и эффективное решение для создания таблиц.

Пошаговая инструкция


import tkinter as tk
from tkinter import ttk

root = tk.Tk()
tree = ttk.Treeview(root, columns=("ID", "Имя", "Возраст"), show="headings")
tree.heading("ID", text="ID")
tree.heading("Имя", text="Имя")
tree.heading("Возраст", text="Возраст")
tree.insert("", tk.END, values=(1, "Анна", 25))
tree.insert("", tk.END, values=(2, "Борис", 30))
tree.pack(fill="both", expand=True)
root.mainloop()

Python self tkinter (использование self в tkinter)

Параметр show="headings" скрывает первый столбец с иконками, оставляя только заголовки. Для добавления строк используется метод insert, где первый аргумент "" означает корневой уровень.

Типичная ошибка: отсутствие show="headings" приводит к появлению пустого столбца слева. Решение - всегда указывать show="headings" при создании таблицы.

Ещё одна проблема: Treeview не позволяет редактировать ячейки напрямую. Для редактирования необходимо использовать дополнительный виджет (Entry) на месте клика.

Как отобразить данные в виде таблицы простыми Label?

Для статического отображения небольшого объёма данных можно разместить виджеты Label в сетке grid. Это не требует дополнительных библиотек, но не поддерживает выделение строк и прокрутку.


data = [("ID", "Имя", "Возраст"), (1, "Анна", 25), (2, "Борис", 30)]
for r, row in enumerate(data):
    for c, val in enumerate(row):
        label = tk.Label(root, text=str(val), borderwidth=1, relief="solid")
        label.grid(row=r, column=c, sticky="nsew")

Tkinter python buttons (кнопки в tkinter (англ.))

Проблемы: сложность добавления прокрутки, неэффективно при большом количестве строк, нет сортировки.

Как сделать редактируемые ячейки с помощью Entry?

Если требуется, чтобы пользователь мог изменять данные, вместо Label используют Entry. Значения можно сохранять через StringVar или событие.


entries = {}
for r in range(1, 3):
    for c in range(3):
        var = tk.StringVar(value=data[r][c])
        entry = tk.Entry(root, textvariable=var)
        entry.grid(row=r, column=c)
        entries[(r,c)] = var

Python tkinter label (метка (label) в tkinter)

Проблемы: требуется управлять расположением, нет встроенной прокрутки, при изменении размера окна ячейки не адаптируются.

Как нарисовать таблицу с помощью Canvas?

Canvas обеспечивает полный контроль над отрисовкой: можно рисовать прямоугольники и текст, управлять цветом, шрифтами. Подходит для нестандартных интерфейсов.


canvas = tk.Canvas(root, width=400, height=300)
canvas.pack()
for i in range(5):
    y = i * 30
    canvas.create_rectangle(0, y, 100, y+30, outline="black")
    canvas.create_text(50, y+15, text=f"Строка {i}")

Python tkinter entry (поле ввода (entry) в tkinter)

Проблемы: нужно самостоятельно обрабатывать события кликов, реализовывать прокрутку, масштабирование. Трудоёмко.

Как использовать стороннюю библиотеку pandastable?

Библиотека pandastable предоставляет виджет Table для отображения DataFrame pandas с возможностями фильтрации, сортировки, редактирования. Устанавливается через pip.


from pandastable import Table, TableModel
import pandas as pd

df = pd.DataFrame({'ID': [1,2], 'Имя': ['Анна','Борис'], 'Возраст': [25,30]})
model = TableModel.getModelFromDataFrame(df)
table = Table(root, model=model)
table.show()

Проблемы: дополнительная зависимость, не всегда поддерживает сложные кастомизации, может конфликтовать с другими виджетами.

- Python tkinter line (рисование линий в tkinter)
- Python tkinter окно (создание окна в tkinter)
- Python tkinter таблицы (создание таблиц в tkinter python)

Расширенные примеры использования Treeview

Сортировка строк по столбцам

Для сортировки привяжем обработчик к событию нажатия на заголовок. Определим номер столбца и переставим строки.

Пример

import tkinter as tk
from tkinter import ttk

def sort_column(tree, col, reverse):
    items = [(tree.set(item, col), item) for item in tree.get_children('')]
    items.sort(reverse=reverse)
    for index, (val, item) in enumerate(items):
        tree.move(item, '', index)
    tree.heading(col, command=lambda: sort_column(tree, col, not reverse))

root = tk.Tk()
tree = ttk.Treeview(root, columns=('Name', 'Age'), show='headings')
tree.heading('Name', text='Name', command=lambda: sort_column(tree, 'Name', False))
tree.heading('Age', text='Age', command=lambda: sort_column(tree, 'Age', False))
tree.insert('', tk.END, values=('Alice', 30))
tree.insert('', tk.END, values=('Bob', 25))
tree.pack()
root.mainloop()
После запуска при клике на заголовок столбца строки сортируются по возрастанию, повторный клик меняет порядок.

Редактирование ячейки по двойному щелчку

При двойном клике определяется ячейка, поверх неё создаётся виджет Entry, который после потери фокуса сохраняет значение.

Пример

import tkinter as tk
from tkinter import ttk

def on_double_click(event):
    item = tree.selection()[0]
    col = tree.identify_column(event.x)  # #1, #2...
    col_index = int(col.replace('#', '')) - 1
    x, y, width, height = tree.bbox(item, column=col)
    value = tree.item(item, 'values')[col_index]
    entry = tk.Entry(tree)
    entry.place(x=x, y=y, width=width, height=height)
    entry.insert(0, value)
    entry.focus()
    def save(event):
        new_val = entry.get()
        values = list(tree.item(item, 'values'))
        values[col_index] = new_val
        tree.item(item, values=values)
        entry.destroy()
    entry.bind('', save)
    entry.bind('', save)

root = tk.Tk()
tree = ttk.Treeview(root, columns=('Name', 'Age'), show='headings')
tree.heading('Name', text='Name')
tree.heading('Age', text='Age')
tree.insert('', tk.END, values=('Alice', 30))
tree.insert('', tk.END, values=('Bob', 25))
tree.bind('', on_double_click)
tree.pack()
root.mainloop()
После двойного щелчка по ячейке появляется поле ввода. При нажатии Enter или уходе фокуса значение сохраняется.

Цветовое выделение строк с помощью тегов

Метод tag_configure позволяет задать цвета фона, шрифта для строк с определённым тегом.

Пример

import tkinter as tk
from tkinter import ttk

root = tk.Tk()
tree = ttk.Treeview(root, columns=('Item', 'Price'), show='headings')
tree.heading('Item', text='Товар')
tree.heading('Price', text='Цена')

tree.tag_configure('even', background='#f0f0f0')
tree.tag_configure('odd', background='#ffffff')
tree.tag_configure('expensive', foreground='red')

for i in range(10):
    tags = ('even',) if i % 2 == 0 else ('odd',)
    price = 100 + i * 10
    if price > 140:
        tags += ('expensive',)
    tree.insert('', tk.END, values=(f'Товар {i+1}', price), tags=tags)

tree.pack()
root.mainloop()
Строки таблицы поочерёдно окрашены в серый и белый, а строки с ценой выше 140 имеют красный текст.

Прокрутка и множественный выбор

Добавим вертикальную полосу прокрутки и разрешим выбор нескольких строк.

Пример

import tkinter as tk
from tkinter import ttk

root = tk.Tk()
frame = tk.Frame(root)
frame.pack(fill='both', expand=True)

scrollbar = ttk.Scrollbar(frame, orient='vertical')
tree = ttk.Treeview(frame, columns=('Name', 'Score'), show='headings',
                    yscrollcommand=scrollbar.set, selectmode='extended')
tree.heading('Name', text='Имя')
tree.heading('Score', text='Баллы')

for i in range(50):
    tree.insert('', tk.END, values=(f'Студент {i}', i*10))

tree.pack(side='left', fill='both', expand=True)
scrollbar.config(command=tree.yview)
scrollbar.pack(side='right', fill='y')

root.mainloop()
Окно содержит таблицу с полосой прокрутки. Зажав Ctrl, можно выбрать несколько строк.

Создание таблиц в Tkinter Python - comments

En
Python tkinter таблицы (python)