파이썬 tkinter Treeview 컬럼 너비 자동 조절 문제 해결 방안

동적으로 크기가 조절되는 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 컨트롤의 크기가 변경될 때 컬럼 너비가 자동으로 적절히 조절되도록 할 수 있습니다.

태그: 파이썬 Tkinter TreeView GUI 컬럼 너비 조절

7월 19일 20:17에 게시됨