Я пытаюсь создать приложение tkinter из 5 столбцов и 2 строк, содержащее ttk.Treeview в верхней строке (охватывающее все 5 столбцов). Нижняя строка должна содержать ttk.Frame в каждом столбце. Ширина фреймов должна соответствовать ширине столбцов древовидного представления. Я добился такого поведения с помощью специального класса пустого фрейма MyFrameResizable. Однако как только я заполняю пользовательский фрейм (
import tkinter as tk
from tkinter import ttk
class MyFrame(ttk.Frame):
def __init__(self, master = None, **kwargs):
super().__init__(master, **kwargs)
self.columnconfigure(0, weight=0)
self.columnconfigure(0, weight=1)
self.rowconfigure(0, weight=1)
# adding other widgets will destroy resizing behavior
self.button = tk.Button(self)
self.button.grid(column=0, row=0, sticky="nesw")
self.entry = tk.Entry(self)
self.entry.grid(column=1, row=0, sticky="nesw")
class MyFrameResizable(ttk.Frame):
def __init__(self, master = None, **kwargs):
super().__init__(master, **kwargs)
self.columnconfigure(0, weight=0)
self.columnconfigure(0, weight=1)
self.rowconfigure(0, weight=1)
class ResizableApp:
def __init__(self, root):
self.root = root
self.root.title("Resizable Grid Example")
# Treeview with 5 columns
self.treeview = ttk.Treeview(root, columns=("Col1", "Col2", "Col3", "Col4", "Col5"), show="headings")
for i, col in enumerate(("Col1", "Col2", "Col3", "Col4", "Col5"), start=1):
self.treeview.heading(f"# {i}", text=col)
self.treeview.column(f"# {i}", width=100, anchor="center") # Initial column widths
self.treeview.grid(row=0, column=0, columnspan=5, sticky="nsew")
# Create bottom row frames with different colors
self.style = ttk.Style()
self.frames = []
colors = ["red", "green", "blue", "yellow", "cyan"]
for i, color in enumerate(colors):
self.style.configure(style_name:=f"Custom{i}.TFrame", background=color)
# change to MyFrame breaks resizing behavior
frame = MyFrameResizable(root, height=10, style=style_name)
frame.grid(row=1, column=i, sticky="nsew")
self.frames.append(frame)
# Configure grid weights for resizing
root.grid_rowconfigure(0, weight=1) # Treeview row resizes with window
root.grid_rowconfigure(1, weight=1) # Frame row stays fixed
for i in range(5):
root.grid_columnconfigure(i, weight=1)
# Bind resizing events to update frame widths
self.treeview.bind("", self.update_frame_widths)
self.treeview.bind("", self.update_frame_widths)
self.treeview.bind("", self.update_frame_widths)
def update_frame_widths(self, event=None):
"""Update the widths of frames to match Treeview column widths."""
print("update")
for i, frame in enumerate(self.frames):
col_width = self.treeview.column(f"# {i + 1}", option="width") # Get current column width
frame.config(width=col_width)
# Run the app
if __name__ == "__main__":
root = tk.Tk()
app = ResizableApp(root)
root.mainloop()
Я ожидал, что менеджер макета сетки назначит ширину фреймам независимо от их содержимого. Я думал, что после определения ширины фрейма дочерние виджеты фрейма будут распределены по сетке в соответствии с доступным пространством.
Однако кажется, что включение дочерних виджетов переопределяет ширину столбца, установленную через конфигурация столбца. Почему это?
Я пытаюсь создать приложение tkinter из 5 столбцов и 2 строк, содержащее ttk.Treeview в верхней строке (охватывающее все 5 столбцов). Нижняя строка должна содержать ttk.Frame в каждом столбце. Ширина фреймов должна соответствовать ширине столбцов древовидного представления. Я добился такого поведения с помощью специального класса пустого фрейма MyFrameResizable. Однако как только я заполняю пользовательский фрейм ([code]MyFrame[/code]) с другими виджетами поведение при изменении размера нарушается. [code]import tkinter as tk from tkinter import ttk
class MyFrame(ttk.Frame): def __init__(self, master = None, **kwargs): super().__init__(master, **kwargs)
# Create bottom row frames with different colors self.style = ttk.Style() self.frames = [] colors = ["red", "green", "blue", "yellow", "cyan"] for i, color in enumerate(colors): self.style.configure(style_name:=f"Custom{i}.TFrame", background=color)
def update_frame_widths(self, event=None): """Update the widths of frames to match Treeview column widths.""" print("update") for i, frame in enumerate(self.frames): col_width = self.treeview.column(f"# {i + 1}", option="width") # Get current column width frame.config(width=col_width)
# Run the app if __name__ == "__main__": root = tk.Tk() app = ResizableApp(root) root.mainloop() [/code] Я ожидал, что менеджер макета сетки назначит ширину фреймам независимо от их содержимого. Я думал, что после определения ширины фрейма дочерние виджеты фрейма будут распределены по сетке в соответствии с доступным пространством. Однако кажется, что включение дочерних виджетов переопределяет ширину столбца, установленную через конфигурация столбца. Почему это?