【问题标题】:tkinter treeview not resizing width when column width changes当列宽发生变化时,tkinter treeview 不会调整宽度
【发布时间】:2019-12-12 10:23:35
【问题描述】:

我有一个包含树视图和按钮的框架。当按下按钮时,树视图的行被删除,列被重新创建并命名标题。列设置为拉伸,树本身设置为扩展。

我的理解是这种配置应该导致列拉伸以匹配包含框架。

在第一次启动时,列会调整大小,并且框架与树视图的预期大小相匹配。然后我按下按钮重新分配和重新调整列的大小(调用与初始化相同的函数)。

列调整大小但树视图保持相同的整体宽度。如果我拖动窗口的右边缘,则树视图会随着框架缩小。当框架“接触”最右边的一列时,它似乎恢复了它的“弹性”,并且随着我调整窗口大小,列会增大/缩小。

此外,有时(每两次启动),列的宽度设置不会影响按钮的第一次点击;我从未在任何后续点击中看到此问题。

我搜索了几篇类似的帖子,但它们指出扩展为假,但我在self.tree.pack() 中设置为真,在listbox.pack() 中设置为包含框架。我尝试不展开并填写两个 pack() 语句;行为是相同的。

当我调整它包含的列的大小时,为什么树视图没有调整大小?什么可能导致第一次点击无法调整列的大小?


    import tkinter as tk
    import tkinter.font as tkFont
    import tkinter.ttk as ttk
    import random
    # import natsort as ns


    class MultiColumnListbox(tk.Frame):
        """Creates a multi-column "listbox" with sorting columns from a treeview class"""

        def __init__(self, master=None,  *args, **kwargs):
            tk.Frame.__init__(self, master=master,*args, **kwargs)
            # add a button to change columns
            tk.Button(self, text="change columns", command=self._populate_dummy).pack(anchor=tk.NW, pady=5)
            self.tree = ttk.Treeview(master=self, show="headings")  # don't show tree column
            self.tree.pack(fill=tk.X, expand=True)                   # place tree in the parent frame

            # initialize to random values
            self._populate_dummy()

        def _populate_dummy(self):
            # generate column names
            colnames = ["item number"]
            numcols = random.randint(1,6)
            colnames += ['col{}'.format(i) for i in range(numcols)]
            self.set_headers(colnames)

            # generate row contents
            rows = []
            for i in range(20):
                vals = ['item{}'.format(i)]
                for _ in range(numcols):
                    vals += [random.randint(1,100)]
                rows.append(tuple(vals))
            self.set_rows(rows)

        # set the table headers
        def set_headers(self, columns):
            self.tree.configure(columns=columns)

            for i, col in enumerate(columns):
                column_width = tkFont.Font().measure(col.title())
                self.tree.heading(i, text=col)
                self.tree.column(i, width=column_width, stretch=True)   # add column, set width to match header

        # set the row values
        def set_rows(self, rows):
            # clear rows
            for child in self.tree.get_children():
                self.tree.delete(child)
            # apply new rows
            for i, item in enumerate(rows):
                tags = [(), ('oddrow',)]
                self.tree.insert('', 'end', values=item, tags=tags[i%2])
            self.tree.tag_configure('oddrow', background='gray80')


    if __name__ == '__main__':
        root = tk.Tk()
        root.title("Multicolumn Treeview/Listbox")
        listbox = MultiColumnListbox(root)
        listbox.pack(padx=10, pady=10, fill=tk.X, expand=True)
        root.mainloop()

此图显示了程序在红色描述的条件下的状态。

更新

我已将 set_headers() 包装为调用以获取树视图及其包含框架(自身)的宽度,因此 _populate_dummy() 现在是:

def _populate_dummy(self):
        # generate column names
        colnames = ["item number"]
        numcols = random.randint(1,6)
        colnames += ['col{}'.format(i) for i in range(numcols)] + []

        print("BEFORE")
        print("frame width: {}".format(frame_width))
        tree_width = self.tree.winfo_width()
        print("table width: {}".format(tree_width))
        self.set_headers(colnames)
        print("AFTER")
        frame_width = self.winfo_width()
        print("frame width: {}".format(frame_width))
        tree_width = self.tree.winfo_width()
        print("table width: {}".format(tree_width))

有趣的是,当程序在构造函数中调用 _populate_dummy() 时,this 返回

BEFORE
frame width: 1
table width: 1
AFTER
frame width: 1
table width: 1

尽管视觉外观相当大。 但此后,一个(非1)值。当我得到“未调整大小”的版本(图片中的第 2 步)时,我得到了这个:

frame width: 99
table width: 91
frame width: 99
table width: 91

当我得到一个列大小正确但框架很大的表格时,我得到了这个:

frame width: 1003
table width: 1003
frame width: 1003
table width: 1003

我应该注意到,报告的宽度似乎与列数无关,甚至是一致的;我一次从 2 列中得到 1003,另一次从 2 列中得到 1203。

这似乎很重要,但我不知道如何解释它。

【问题讨论】:

    标签: python-3.x tkinter treeview


    【解决方案1】:

    我不知道为什么树视图在当前情况下会这样,但是 您可以通过在 _populate_dummy 方法中的 colnames 末尾添加一个空标题来解决空格问题

    def _populate_dummy(self):
        # generate column names
        colnames = ["item number"]
        numcols = random.randint(1,6)
        colnames += ['col{}'.format(i) for i in range(numcols)] + ['']
        self.set_headers(colnames)
    

    然后在set_headers方法的最后一行设置空列标题宽度大于当前主窗口宽度

    def set_headers(self, columns):
        self.tree.configure(columns=columns)
        for i, col in enumerate(columns):
            column_width = tkFont.Font().measure(col.title())
            self.tree.heading(i, text=col)
            self.tree.column(i, width=column_width, stretch=True)   # add column, set width to match header
        self.tree.column(i, width=self.winfo_width())
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-12-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-02-01
      • 2016-08-15
      • 2023-03-23
      相关资源
      最近更新 更多