【发布时间】: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