Interface-module/frames/CTkTableFrame.py
2025-03-19 13:23:59 +03:00

73 lines
3.3 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import customtkinter as ctk
class CTkTableFrame(ctk.CTkFrame):
def __init__(self, master: ctk.CTk, columns, data: list, callback, width=400, height=200, *args, **kwargs):
super().__init__(master, *args, **kwargs)
self.columns = columns
self.data = data
self._callback = callback
self.configure(width=width, height=height)
self.scroll_frame = ctk.CTkScrollableFrame(self)
self.scroll_frame.pack(fill="both", expand=True, padx=5, pady=5)
def _create_table(self):
"""Создает таблицу с заголовками и данными, используя параметры из словаря."""
for widget in self.scroll_frame.winfo_children():
widget.destroy()
# Применяем шаблон значений по умолчанию
default_column = {"width": 0, "align": "left", "name": "N/A"}
columns = [{**default_column, **col} if type(col) == dict else {**default_column, "name": col} for col in self.columns]
# Функция преобразования align в формат anchor
def parse_align(align):
return {"left": "w", "right": "e", "center": "center"}.get(align, "w")
# Определяем ширины: если текущая ширина меньше вычисленной, то обновляем
for i, col in enumerate(columns):
max_data_width = max((len(str(row[i])) * 7 for row in self.data if i < len(row)), default=0) + 10
if col["width"] < max_data_width:
col["width"] = max_data_width
col["align"] = parse_align(col["align"])
# Заголовки
header_frame = ctk.CTkFrame(self.scroll_frame, fg_color="gray30")
header_frame.pack(fill="x", padx=2, pady=1)
for col in columns:
header_label = ctk.CTkLabel(
header_frame, text=col["name"], width=col["width"], anchor=col["align"], padx=5
)
header_label.pack(side="left", padx=2, pady=3)
# Данные
for row_index, row_data in enumerate(self.data):
row_frame = ctk.CTkFrame(self.scroll_frame, fg_color="gray20", corner_radius=3, height=20)
row_frame.pack(fill="x", padx=2, pady=1)
row_frame.bind("<Double-1>", lambda event, idx=row_index, r=row_data: self._callback({"row_index": idx, "row_data": r}))
for i, col in enumerate(columns):
cell_text = str(row_data[i]) if i < len(row_data) else ""
cell_label = ctk.CTkLabel(row_frame, text=cell_text, width=col["width"], anchor=col["align"], padx=5)
cell_label.pack(side="left", padx=2, pady=2)
cell_label.bind("<Double-1>", lambda event, idx=row_index, r=row_data: self._callback({"row_index": idx, "row_data": r}))
def edit(self, row_index, new_data):
"""Редактирует строку по индексу."""
if 0 <= row_index < len(self.data):
self.data[row_index] = new_data
self.redraw()
def add(self, new_data):
"""Добавляет новую строку."""
self.data.append(new_data)
self.redraw()
def redraw(self):
"""Перерисовывает таблицу."""
self._create_table()