tkinter ttk treeview 如何设置固定宽度?为啥它会随着列数而变化?

Posted

技术标签:

【中文标题】tkinter ttk treeview 如何设置固定宽度?为啥它会随着列数而变化?【英文标题】:tkinter ttk treeview how to set fixed width? why it change with number of column?tkinter ttk treeview 如何设置固定宽度?为什么它会随着列数而变化? 【发布时间】:2019-05-03 18:42:39 【问题描述】:

我正在尝试使用 python tkinter 来构建一个界面来使用 Treeview 显示数据库表信息。标题是表模式,并将数据行插入树视图表。由于不同表中的列数可能不一样,我想自动调整列的宽度,以便树视图表的总宽度是固定的。 我在 Pycharm 2018.3-community 中编写了 python3 代码,并使用函数(显示表)插入数据行并使用“treeview.column(col, width = int(total_width / len(cols)), minwidth=0, anchor ='center',stretch=0 )" 设置列宽。显示页面时调用该函数(我在调用该行时为该行添加注释)。第一次运行代码时,列宽正常调整了宽度,表格总宽度很合适,正确,如下图。

但是,如果我单击一个按钮来调用相同的函数来插入相同的数据行,那么树视图表的宽度会发生变化。我发现它随着列数的变化而变化,如下所示。我不知道为什么会这样。请指教。非常感谢 !我的代码附在底部。

class ListPage(tk.Tk):
table_list = sample.scan_result.table_list
table_index = 0

def __init__(self, parent, controller):
    tk.Frame.__init__(self, parent, bg='#C6E2FF')


    self.tbTitlelabel = tk.Button(self, text="Table", font=("Verdana", 18, "bold"), bg='#C6E2FF', fg='darkblue', command=lambda: controller.show_frame(start_page.StartPage))
    self.tbTitlelabel.grid(row=1, column=0, columnspan=1, padx=(150, 0), sticky='w')

    self.nextLabel = tk.Button(self, text="Next", font=("Verdana", 8, "bold"), bg='#C6E2FF', fg='darkblue',command=lambda:self.nextTable())
    self.nextLabel.grid(row=1, column=0, columnspan=1, padx=(280, 0), sticky='w')

    **# if call the function by the button, the table width change.** 
    self.preLabel = tk.Button(self, text="Previous", font=("Verdana", 18, "bold"), bg='#C6E2FF', fg='darkblue', command=lambda:self.showTable() )   
    self.preLabel.grid(row=1, column=0, columnspan=1, padx=(380, 0), sticky='w')

    style = ttk.Style()
    style.configure("Treeview.Heading", font=("Verdana", 15))
    self.tree = ttk.Treeview(self, height=10, show = 'headings', selectmode='browse')
    self.tree.grid(row=2, column=0, columnspan=1, padx=(120, 0), sticky='w')

    ysb = ttk.Scrollbar(self, orient='vertical', command=self.tree.yview)
    self.tree['yscroll'] = ysb.set
    ysb.grid(row=2, column=0, sticky='ens')

    **# if call the function during the page intial, the table width is good.** 
    self.showTable()  


def nextTable(self):
    if self.table_index < len(self.table_list)-1:
        self.table_index += 1
    self.showTable()

def previousTable(self):
    if self.table_index > 0:
        self.table_index -= 1
    self.showTable()

def showTable(self):
    print('run show table')
    col_start_pos = 0

    for i in self.tree.get_children():
        self.tree.delete(i)

    if len(self.table_list) > self.table_index:
        print(  self.table_index,  self.table_list)

        table_item = self.table_list[self.table_index]
        print(self.table_list[1], self.table_index)
        self.tbTitlelabel['text'] = table_item.db_name
        col_name = table_item.col_name[col_start_pos:]
        self.tree['columns'] = col_name
        data_list = table_item.data_list

        for col in col_name:
            self.tree.heading(col, text=col)
            **self.tree.column(col, width= int(600 / len(col_name)), minwidth=0, anchor='center',stretch=0) # auto adjust column width**

        x=0
        while x < 7:
            for list in data_list:
                self.tree.insert('', 'end', values = list[col_start_pos:] )
            x+=1

【问题讨论】:

请点击“正常宽度”和“更改宽度”查看图片。此外,列宽实际上是自动调整的。它只是右侧显示的一个额外的列,使宽度发生了变化。我不知道那个额外的列是什么,我什至无法单击或拖动它。只是显示问题吗?? 【参考方案1】:

在尝试了 root.update()、treeview.update() 和 treeview.destroy() 之类的所有操作后,我自己也遇到了同样的问题,这弄乱了我所有的 gui。最后通过在清除树视图之前保存列表中列的宽度来修复它,然后使用这些宽度与新的宽度进行比较并使用更大的...

columns = []
wcols = []
row = 1
for each in self.table_tree.get_children():
    if row > 1: break
    columns = list(self.table_tree.item(each, option='values'))
    print(columns)
    for i in range(len(columns)):
        wcols.append(self.table_tree.column(i, width=None))
    row = row + 1

然后是以后

self.table_tree["columns"]=column_names
indx = 0
h_col_w = []
new_col_w = []
for i in column_names:
    h_col_w.append(tkFont.Font().measure(i))
    if not(wcols == []):
        if h_col_w[indx] < wcols[indx]:
            h_col_w[indx] = wcols[indx]
    self.table_tree.column(i, width=h_col_w[indx], stretch=True) ;"set the width of the column to the width of the column name"
        self.table_tree.heading(i, text=i, command= lambda _col=i: \
                                self.treeview_sort_column(self.table_tree, _col, True))
        indx = indx + 1

【讨论】:

【参考方案2】:

我在刷新树时这样做:

self.geometry(self.winfo_geometry())

“自我”是树的主人。 当我通过 tree.config(columns=new_columns) 在树上添加新列时,树将自行调整大小,但不会使用上述命令调整大小。该命令可以放在配置之前或之后。但是很抱歉我不知道原因。

【讨论】:

【参考方案3】:

经过多次尝试,我自己找到了解决方案。我把它放在下面,以防有人遇到同样的问题。 就像我之前说的,第一次生成treeview 表时,表width 是正确的。因此,每次我们需要展示一个表时,我们需要销毁旧的treeview.destory(),然后创建一个新的treeview,然后插入数据。

【讨论】:

【参考方案4】:

我知道这是一个旧线程,但我最近遇到了类似的问题,更新选项不起作用,销毁不是一个选项。这个决议对我来说很简单。一旦我将show = 'headings' 移动到对列宽进行所有最终调整后,一切都会正确显示。如果 init 方法中的行:

self.tree = ttk.Treeview(self, height=10, show = 'headings', selectmode='browse')

替换为:

self.tree = ttk.Treeview(self, height=10, selectmode='browse')

并在showTable方法的末尾添加以下内容:

self.tree['show'] = 'headings'

那么它应该渲染得很好。

【讨论】:

以上是关于tkinter ttk treeview 如何设置固定宽度?为啥它会随着列数而变化?的主要内容,如果未能解决你的问题,请参考以下文章

Python如何改变tkinter.ttk.Treeview表格组件的每行的行高?

如何使用 Tkinter 清除整个 Treeview

python 3 - tkinter - ttk treeview:查看列文本

强制 Tkinter.ttk Treeview 小部件在缩小其列宽后调整大小

ttk.Treeview - 无法更改行高

在 tkinter ttk treeview 中格式化单个单元格/项目而不是整行