동적으로 크기가 조절되는 GUI 창에서 Treeview 컨트롤을 사용할 때 발생하는 컬럼 너비 자동 조절 문제를 해결하는 방법을 소개합니다.
기존 코드 문제점:
from tkinter import *
from tkinter.ttk import *
class DataTableFrame(Frame):
def __init__(self, master, **kwargs):
super().__init__(master, **kwargs)
self.data_tree = self.create_data_table()
self.horizontal_scroll, self.vertical_scroll = self.create_scrollbars(self.data_tree)
def create_data_table(self):
table_widget = Treeview(self, show="headings", columns=("item_name", "item_path"))
table_widget.column("item_name", anchor="center", stretch=False)
table_widget.heading("item_name", text="이름", anchor=CENTER)
table_widget.column("item_path", anchor="center", stretch=True)
table_widget.heading("item_path", text="경로", anchor='center')
return table_widget
def create_scrollbars(self, tree_widget):
x_scroll = Scrollbar(self, orient=HORIZONTAL)
y_scroll = Scrollbar(self, orient=VERTICAL)
tree_widget.config(xscrollcommand=x_scroll.set, yscrollcommand=y_scroll.set)
x_scroll.config(command=tree_widget.xview)
y_scroll.config(command=tree_widget.yview)
return x_scroll, y_scroll
def arrange_components(self):
self.horizontal_scroll.pack(side=BOTTOM, fill=X)
self.vertical_scroll.pack(side=RIGHT, fill=Y)
self.data_tree.pack(fill=BOTH, expand=1)
def pack(self, cnf={}, **kw):
super().pack(cnf, kw)
self.arrange_components()
def grid(self, cnf={}, **kw):
super().grid(cnf, kw)
self.arrange_components()
main_window = Tk()
main_window.geometry("500x500")
data_app = DataTableFrame(main_window)
data_app.pack(fill=BOTH, expand=True)
main_window.mainloop()
수동으로 컬럼 경계를 드래그하여 너비를 조절할 경우, 표의 범위를 초과하거나 미달하는 문제가 발생합니다.
해결 방안: Treeview 컨트롤에 <ButtonRelease-1> 이벤트를 바인딩하여 다음과 같이 처리합니다:
def adjust_column_widths(event):
container_width = data_app.data_tree.winfo_width()
first_col_width = data_app.data_tree.column("item_name", "width")
second_col_width = data_app.data_tree.column("item_path", "width")
if first_col_width > container_width:
# 첫 번째 컬럼 너비가 컨트롤 길이보다 클 경우
data_app.data_tree.column("item_name", width=100)
data_app.data_tree.column("item_path", width=container_width - 100)
else:
# 첫 번째 컬럼 너비가 컨트롤 길이보다 작지만 두 컬럼 합이 컨트롤 길이와 다를 경우
if first_col_width + second_col_width != container_width:
data_app.data_tree.column("item_path", width=container_width - first_col_width)
전제 조건은 고정값이 창의 최소 설정값보다 작아야 합니다. 나머지는 실제 상황에 맞게 조정합니다.
완성된 코드:
from tkinter import *
from tkinter.ttk import *
class DataTableFrame(Frame):
def __init__(self, master, **kwargs):
super().__init__(master, **kwargs)
self.data_tree = self.create_data_table()
self.horizontal_scroll, self.vertical_scroll = self.create_scrollbars(self.data_tree)
def create_data_table(self):
table_widget = Treeview(self, show="headings", columns=("item_name", "item_path"))
table_widget.column("item_name", anchor="center", stretch=False)
table_widget.heading("item_name", text="이름", anchor=CENTER)
table_widget.column("item_path", anchor="center", stretch=True)
table_widget.heading("item_path", text="경로", anchor='center')
return table_widget
def create_scrollbars(self, tree_widget):
x_scroll = Scrollbar(self, orient=HORIZONTAL)
y_scroll = Scrollbar(self, orient=VERTICAL)
tree_widget.config(xscrollcommand=x_scroll.set, yscrollcommand=y_scroll.set)
x_scroll.config(command=tree_widget.xview)
y_scroll.config(command=tree_widget.yview)
return x_scroll, y_scroll
def arrange_components(self):
self.horizontal_scroll.pack(side=BOTTOM, fill=X)
self.vertical_scroll.pack(side=RIGHT, fill=Y)
self.data_tree.pack(fill=BOTH, expand=1)
def pack(self, cnf={}, **kw):
super().pack(cnf, kw)
self.arrange_components()
def adjust_column_widths(event):
container_width = data_app.data_tree.winfo_width()
first_col_width = data_app.data_tree.column("item_name", "width")
second_col_width = data_app.data_tree.column("item_path", "width")
if first_col_width > container_width:
# 첫 번째 컬럼 너비가 컨트롤 길이보다 클 경우
data_app.data_tree.column("item_name", width=100)
data_app.data_tree.column("item_path", width=container_width - 100)
else:
# 첫 번째 컬럼 너비가 컨트롤 길이보다 작지만 두 컬럼 합이 컨트롤 길이와 다를 경우
if first_col_width + second_col_width != container_width:
data_app.data_tree.column("item_path", width=container_width - first_col_width)
main_window = Tk()
main_window.geometry("500x500")
data_app = DataTableFrame(main_window)
data_app.data_tree.bind("<ButtonRelease-1>", adjust_column_widths)
data_app.pack(fill=BOTH, expand=True)
main_window.mainloop()
이 방법을 통해 Treeview 컨트롤의 크기가 변경될 때 컬럼 너비가 자동으로 적절히 조절되도록 할 수 있습니다.