我在使用ttk.Treeview
和ttk.Notebook
布局管理器布置两个相同的grid
小部件时遇到问题。当我只使用一个树视图(放在一个labelframe中,放在一个框架(部分)中时,它放在另一个框架中( main ),放在 root ),然后一切正常,我得到了预期的结果:
但是当我尝试在笔记本中放置两个这样的树视图时,一切都变得混乱,即使我没有改变代码中的任何内容,分开添加笔记本:
这里是我根据the SO guidelines编写的代码,以更好地说明问题(我试图尽可能缩短它,同时保留应用程序的重要特征(如列布局和滚动条)它被取出了:
import tkinter as tk
from tkinter import ttk
root = tk.Tk()
root.title("App")
mainframe = ttk.Frame(root)
mainframe.grid()
section = ttk.Frame(mainframe, padding=(0, 0, 10, 60))
section.grid(sticky="nsew")
labelframe = ttk.Labelframe(section, text="Title", padding=(5, 7, 5, 13))
labelframe.grid(sticky="nsew")
# styles
style = ttk.Style()
style.configure(
"App.Treeview",
font=("TkDefaultFont", 8),
rowheight=15
)
style.configure(
"App.Treeview.Heading",
font=("TkDefaultFont", 8)
)
def build_tree(parent):
# treeview
trv = ttk.Treeview(parent)
trv.configure(
style="App.Treeview",
height=19,
columns=("#1", "#2", "#3", "#4"),
displaycolumns="#all",
selectmode="browse"
)
trv.grid(column=0, row=0, sticky="nsew")
# treeview's scrollbars
sbar_vertical = ttk.Scrollbar(parent, orient=tk.VERTICAL, command=trv.yview)
sbar_vertical.grid(column=1, row=0, sticky="ns")
sbar_horizontal = ttk.Scrollbar(parent, orient=tk.HORIZONTAL, command=trv.xview)
sbar_horizontal.grid(column=0, row=1, sticky="we")
trv.configure(yscrollcommand=sbar_vertical.set, xscrollcommand=sbar_horizontal.set)
# treeview's columns
trv.heading("#1", text="Name_1")
trv.heading("#2", text="Pos")
trv.heading("#3", text="NT/R")
trv.heading("#4", text="★")
trv.column("#0", stretch=True, minwidth=70, width=49)
trv.column("#1", stretch=True, minwidth=97, width=49)
trv.column("#2", stretch=True, minwidth=35, width=49)
trv.column("#3", stretch=True, minwidth=40, width=49, anchor=tk.E)
trv.column("#4", stretch=True, minwidth=12, width=49)
return trv
# tree = build_tree(labelframe)
# notebook
notebook = ttk.Notebook(labelframe)
tree1 = build_tree(notebook)
tree2 = build_tree(notebook)
notebook.add(tree1, text="One")
notebook.add(tree2, text="Two")
notebook.grid(sticky="nsew")
root.resizable(False, False)
root.mainloop()
要在第一个结果和第二个结果之间切换,必须取消注释
# tree = build_tree(labelframe)
排除并注释掉# notebook
部分。
我尝试在构造函数中提供笔记本height
和weight
选项参数,但没有任何更改,也尝试添加
rowconfigure(0, weight=1)
columnconfigure(0, weight=1)
到每个级别的容器(mainframe
,section
和labelframe
),甚至全部到笔记本和树视图(即使AFAIK这只应该是必要的,如果窗口是可以调整大小) - 获得完全相同的结果。
我的理解是,如果小部件放在grid
中,而没有任何选项传递给grid()
,那么放置的小部件决定需要多少空间{ {1}}管理器将给定列的宽度(或行的高度)容纳到窗口小部件请求的最高值(在给定列或行中管理的所有值)。然后,如果这样的决定空间对于使用相同行/列的其他小部件来说太大,那么它会被拉伸(或者没有 - 主要根据grid
选项)。如果这种理解是正确的,那么我不太了解笔记本的行为,特别是因为单独的树视图似乎完全符合它。
我的环境:Ubuntu 17.10,Python 3.6.3,Tkinter 8.6。 如果是treeview列'设置看起来有点奇怪 - 它来自a comment to this question,并且必须像使用水平滚动条一样。
答案 0 :(得分:1)
问题是您尝试使用grid
将滚动条和树视图添加到笔记本中,然后使用笔记本的add
方法添加它们。你不能把两者混在一起。创建笔记本时,不应通过pack
,place
或grid
直接向其添加小部件。
相反,每个笔记本标签应该是一个框架。然后,您可以使用pack
,place
或grid
将任何其他小部件放在该框架内。然后,使用add
将此框架添加到笔记本中。
因此,您的第一步是修改build_tree
以创建并返回一个框架:
def build_tree(parent):
frame = ttk.Frame(frame)
...
return frame
接下来,您需要确保树和滚动条是此框架的子项而不是笔记本的子项:
trv = ttk.Treeview(frame)
sbar_vertical = ttk.Scrollbar(frame, ...)
sbar_horizontal = ttk.Scrollbar(frame, ...)
根据经验,每当您使用grid
时,您应该始终给予至少一行和一列非零重量,以便它们增长和缩小以填充任何额外空间。因此,请确保设置此帧的行和列的权重。
例如:
def build_tree(parent):
...
frame.grid_rowconfigure(0, weight=1)
frame.grid_columnconfigure(0, weight=1)
...
现在,这将使笔记本看起来和笔记本电脑的行为正常。
您对所有其他框架的行/列权重问题类似,因此您希望将权重应用于具有由grid
管理的子窗口小部件的每个窗口小部件。