[~] optimize table render

This commit is contained in:
Maxim Khomutov 2025-03-20 19:06:09 +03:00
parent 3efa1a5f8a
commit 71a85fcb6b

View File

@ -1,7 +1,7 @@
import customtkinter as ctk import customtkinter as ctk
class CTkTableFrame(ctk.CTkFrame): class CTkTableFrame(ctk.CTkFrame):
def __init__(self, master: ctk.CTk, columns, data: list, callback, width=400, height=200, *args, **kwargs): def __init__(self, master: ctk.CTk | ctk.CTkToplevel, columns, data: list, callback, width=400, height=200, *args, **kwargs):
super().__init__(master, *args, **kwargs) super().__init__(master, *args, **kwargs)
self.columns = columns self.columns = columns
self.data = data self.data = data
@ -9,17 +9,35 @@ class CTkTableFrame(ctk.CTkFrame):
self.configure(width=width, height=height) 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): def _create_table(self):
event.call("loading.open")
event.call("loading.set_progress", 0)
event.call("loading.set_text", "Таблица")
event.call("loading.set_subtext", "очистка")
"""Создает таблицу с заголовками и данными, используя параметры из словаря.""" """Создает таблицу с заголовками и данными, используя параметры из словаря."""
for widget in self.scroll_frame.winfo_children(): _old_children = self.winfo_children()
for i, widget in enumerate(_old_children):
widget.destroy() widget.destroy()
event.call("loading.set_progress", (i + 1) / len(_old_children))
scroll_frame = ctk.CTkScrollableFrame(self)
event.call("loading.set_progress", 0)
event.call("loading.set_subtext", "настройка")
_need_to_pack = []
# Применяем шаблон значений по умолчанию # Применяем шаблон значений по умолчанию
default_column = {"width": 0, "align": "left", "name": "N/A"} 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] columns = [] # [{**default_column, **col} if type(col) == dict else {**default_column, "name": col} for col in self.columns]
for col in self.columns:
if type(col) == dict:
if "width" not in col:
col["width"] = (len(col["name"]) * 7) + 14
columns.append({**default_column, **col})
else:
columns.append({**default_column, "width": (len(col) * 7) + 14, "name": col})
print(columns)
# Функция преобразования align в формат anchor # Функция преобразования align в формат anchor
def parse_align(align): def parse_align(align):
@ -32,29 +50,43 @@ class CTkTableFrame(ctk.CTkFrame):
col["width"] = max_data_width col["width"] = max_data_width
col["align"] = parse_align(col["align"]) col["align"] = parse_align(col["align"])
event.call("loading.set_progress", 1)
# Заголовки # Заголовки
header_frame = ctk.CTkFrame(self.scroll_frame, fg_color="gray30") header_frame = ctk.CTkFrame(scroll_frame, fg_color="gray30")
header_frame.pack(fill="x", padx=2, pady=1) _need_to_pack.append((header_frame, {"fill": "x", "padx": 2, "pady": 1}))
for col in columns: for col in columns:
header_label = ctk.CTkLabel( header_label = ctk.CTkLabel(
header_frame, text=col["name"], width=col["width"], anchor=col["align"], padx=5 header_frame, text=col["name"], width=col["width"], anchor=col["align"], padx=5
) )
header_label.pack(side="left", padx=2, pady=3) _need_to_pack.append((header_label, {"side": "left", "padx": 2, "pady": 3}))
event.call("loading.set_progress", 0)
event.call("loading.set_subtext", "подготовка данных")
# Данные # Данные
for row_index, row_data in enumerate(self.data): 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 = ctk.CTkFrame(scroll_frame, fg_color="gray20", corner_radius=3, height=20)
row_frame.pack(fill="x", padx=2, pady=1) _need_to_pack.append((row_frame, {"fill": "x", "padx": 2, "pady": 1}))
if self._callback:
row_frame.bind("<Double-1>", lambda event, idx=row_index, r=row_data: self._callback({"row_index": idx, "row_data": r})) 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): for i, col in enumerate(columns):
cell_text = str(row_data[i]) if i < len(row_data) else "" 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 = ctk.CTkLabel(row_frame, text=cell_text, width=col["width"], anchor=col["align"], padx=5)
cell_label.pack(side="left", padx=2, pady=2) _need_to_pack.append((cell_label, {"side": "left", "padx": 2, "pady": 2}))
if self._callback:
cell_label.bind("<Double-1>", lambda event, idx=row_index, r=row_data: self._callback({"row_index": idx, "row_data": r}))
cell_label.bind("<Double-1>", lambda event, idx=row_index, r=row_data: self._callback({"row_index": idx, "row_data": r})) if row_index % 2 == 0:
event.call("loading.set_progress", (row_index + 1) / len(self.data))
event.call("loading.set_progress", 0)
event.call("loading.set_subtext", "отрисовка данных")
for i, (widget, pack_params) in enumerate(_need_to_pack):
if i % 2 == 0:
event.call("loading.set_progress", (i + 1) / len(_need_to_pack))
widget.pack(**pack_params)
scroll_frame.pack(fill="both", expand=True, padx=5, pady=5)
event.call("loading.close")
def edit(self, row_index, new_data): def edit(self, row_index, new_data):
"""Редактирует строку по индексу.""" """Редактирует строку по индексу."""