I'm having trouble laying out two same ttk.Treeview widgets using ttk.Notebook and grid layout manager. When I'm working with only one treeview (placed in a labelframe, that is placed in a frame (section), that is placed in yet another frame (main), that is placed in root), then everything works and I get the desired results:
But as soon as I try putting two such treeviews in a notebook, everything goes haywire, even though I don't change anything in the code, apart from adding a notebook:
Here's the code I prepared according to the SO guidelines to better illustrate the problem (I tried to make it as short as I could while retaining vital characteristics (like the columns layout and scrollbars) of the app it was taken out of) :
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()
To switch between the first result and the second, one has to only uncomment the
# tree = build_tree(labelframe)
line and comment out the # notebook section.
I tried giving the notebook height and weight option arguments in a constructor but nothing changed and also tried with adding
rowconfigure(0, weight=1)
columnconfigure(0, weight=1)
to a container on each level (mainframe, section and labelframe) and even all down to the notebook and the treeviews (even though AFAIK this should only be necessary if the window was to be resizable) - obtaining exactly the same result.
My understanding was if widgets are placed in a grid without any options passed to a grid() call, then a widget placed decides how much space it needs and the grid manager accommodates a given column's width (or a height in case of a row) to the highest value requested by the widget (of all managed in a given column or row). Then if such decided space is too big for some other widget that uses the same row/column, then it gets stretched (or no - according mainly to the sticky option). If that understanding is correct, then I don't quite understand the notebook's behavior, especially as the alone treeview seems to perfectly adhere to it.
My environment: Ubuntu 17.10, Python 3.6.3, Tkinter 8.6. In case the treeview columns' setup looks somewhat peculiar - it was derived from a comment to this question and has to be like that to make use of the horizontal scrollbar.

