Reputation: 115
I'm using Tkinter
and ttk
in Python 2.7.11 to create a GUI, which is basically a converter for datasets. This part is working without a problem. The help window I'm programming however, gives me headaches.
Currently the help is a Tkinter.Toplevel
and structured via Notebooks
, which include ttk.Frames
, ttk.LabelFrames
and ttk.Labels
. My problem here is, that the frames of the different notebooks and the labelframes with the labels inside don't stick properly. If for example one entry is 50 characters long and all other entries are 20 characters long, the whole window will stretch to 50 characters (which is fine), but the frames and labels containing the 20 chars will not propagate, if they are not within the same notebookentry.
I honestly don't know, if I'm using the weight
wrong or if I'm overlooking some other detail.
You can see some example code without labelframes here (no labelframes to shorten the example code):
# -*- coding: utf-8 -*-
import Tkinter
import ttk
import align_text
class NotebookApp:
# Initiate modules
def __init__(self, parent):
self.my_parent = parent
self.globalStyle()
self.myNotebookEntries()
self.myNotebook()
self.closeButton()
# Set global style:
def globalStyle(self):
# Style:
style_global = ttk.Style()
style_global.theme_use('winnative')
# Create and define the notebook:
def myNotebook(self):
bd_width = 2
relief = 'ridge'
# Top Notebook:
top_notebook = ttk.Notebook(self.my_parent)
top_notebook.grid(column = 0, row = 0)
# Tabs of top Notebook:
first_tab_of_top = ttk.Frame(top_notebook)
second_tab_of_top = ttk.Frame(top_notebook)
# Notebook of tab one:
nb_one_of_top = ttk.Notebook(first_tab_of_top)
nb_one_of_top.grid(column = 0, row = 0)
# Notebook of tab two:
nb_two_of_top = ttk.Notebook(second_tab_of_top)
nb_two_of_top.grid(column = 0, row = 0)
# Tabs of the Notebook of tab one:
first_tab_of_nb_one = ttk.Frame(nb_one_of_top)
first_tab_of_nb_one.grid(column = 0, row = 0, sticky = 'ew')
first_tab_of_nb_one.grid_columnconfigure(0, weight = 1)
second_tab_of_nb_one = ttk.Frame(nb_one_of_top)
second_tab_of_nb_one.grid(column = 0, row = 0, sticky = 'ew')
second_tab_of_nb_one.grid_columnconfigure(0, weight = 1)
# Tabs of the Notebook of tab two:
first_tab_of_nb_two = ttk.Frame(nb_two_of_top)
first_tab_of_nb_two.grid(column = 0, row = 0, sticky = 'ew')
first_tab_of_nb_two.grid_columnconfigure(0, weight = 1)
second_tab_of_nb_two = ttk.Frame(nb_two_of_top)
second_tab_of_nb_two.grid(sticky = 'ew')
second_tab_of_nb_two.grid_columnconfigure(0, weight = 1)
# Adding the Tabs (Frames) of the top Notebook:
top_notebook.add(first_tab_of_top, text = self.first_tab_of_top_txt)
top_notebook.add(second_tab_of_top, text = self.second_tab_of_top_txt)
# Adding the Tabs (Frames) of the Notebook of tab one of the top Notebook:
nb_one_of_top.add(first_tab_of_nb_one, text = self.first_tab_of_nb_one_txt)
nb_one_of_top.add(second_tab_of_nb_one, text = self.second_tab_of_nb_one_txt)
# Adding the Tabs (Frames) of the Notebook of tab two of the top Notebook:
nb_two_of_top.add(first_tab_of_nb_two, text = self.first_tab_of_nb_two_txt)
nb_two_of_top.add(second_tab_of_nb_two, text = self.second_tab_of_nb_two_txt)
# Add Labels to the Tabs (Frames) of the Notebook of tab one of the top Notebook:
label_one_of_nb_one_of_top = ttk.Label(first_tab_of_nb_one,
text = '\n'.join(align_text.align_paragraph(
self.label_one_of_nb_one_of_top_txt,
width = 50,
debug = 0)),
borderwidth = bd_width,
relief = relief)
label_one_of_nb_one_of_top.grid(column = 0, row = 0, sticky = 'nsew')
label_one_of_nb_one_of_top.grid_columnconfigure(0, weight = 1)
label_two_of_nb_one_of_top = ttk.Label(second_tab_of_nb_one,
text = self.label_two_of_nb_one_of_top_txt,
borderwidth = bd_width,
relief = relief)
label_two_of_nb_one_of_top.grid(column = 0, row = 0, sticky = 'nsew')
label_two_of_nb_one_of_top.grid_columnconfigure(0, weight = 1)
# Add Labels to the Tabs (Frames) of the Notebook of tab two of the top Notebook:
label_one_of_nb_two_of_top = ttk.Label(first_tab_of_nb_two,
text = self.label_one_of_nb_two_of_top_txt,
borderwidth = bd_width,
relief = relief)
label_one_of_nb_two_of_top.grid(column = 0, row = 0, sticky = 'nsew')
label_one_of_nb_two_of_top.grid_columnconfigure(0, weight = 1)
label_two_of_nb_two_of_top = ttk.Label(second_tab_of_nb_two,
text = self.label_two_of_nb_two_of_top_txt,
borderwidth = bd_width,
relief = relief)
label_two_of_nb_two_of_top.grid(column = 0, row = 0, sticky = 'nsew')
label_two_of_nb_two_of_top.grid_columnconfigure(0, weight = 1)
# All notebookentries:
def myNotebookEntries(self):
self.first_tab_of_top_txt = "First Notebook"
self.second_tab_of_top_txt = "Second Notebook"
self.first_tab_of_nb_one_txt = "First Tab"
self.second_tab_of_nb_one_txt = "Second Tab"
self.first_tab_of_nb_two_txt = "First Tab"
self.second_tab_of_nb_two_txt = "Second Tab"
self.label_one_of_nb_one_of_top_txt = ("This is the text of the first "
"label of the first notebook."
"It is somewhat longer, than the "
"second one.")
self.label_two_of_nb_one_of_top_txt = "Text of Label two of notebook one."
self.label_one_of_nb_two_of_top_txt = "Text of Label one of notebbok two."
self.label_two_of_nb_two_of_top_txt = "Text of Label two of notebbok two."
# Button to close the notebook:
def closeButton(self):
close_button = ttk.Button(self.my_parent, text = "Close App",
command = self.closeButtonClick)
close_button.bind('<Return>', self.wrapperCloseButton)
close_button.grid(column = 0, row = 1)
# Command, used by the close button:
def closeButtonClick(self):
self.my_parent.destroy()
def wrapperCloseButton(self, event):
self.closeButtonClick()
# Main:
if __name__ == '__main__':
root = Tkinter.Tk()
root.title("Simple Notebbok")
notebook_app = NotebookApp(root)
root.mainloop()
I've also read about two seemingly similar issue, but with the distribution of frames and buttons. In both cases the proper use of weight
helped to achieve the goals of each programmer. Since I'm writing a help for the users of my converter, there is multiline-text, which is separated by the align_paragraph
function of the recipe 414870 by Denis Barmenkov. However, there seems to be no difference regarding the sticky
property, whether I use this function to autosize my text or not. There seems also no difference between using grid_columnconfigure
or columnconfigure
.
Upvotes: 1
Views: 4053
Reputation: 385970
You seem to have a misunderstanding of what column weights do, and how to use them, and how the sticky
attribute interacts with columns.
The weight of a column only affects how excess space is allocated to a column. If a column has a weight, it is given some (or all) of the extra space. Also, the weight only affects interior widgets, not the widget itself. For example, foo.grid_columnconfigure(weight=1)
only affects widgets placed inside foo
, and has no affect on how foo
is allocated space inside its parent.
Your first problem seems to be that you don't give any weight to any columns in the window as a whole (ie: the parent of top_notebook
). If you want top_notebook
to be given extra space in the parent (grow and shrink with the window), you need to give weight to the rows and columns of its parent.
For example:
self.my_parent.grid_columnconfigure(0, weight=1)
self.my_parent.grid_rowconfigure(0, weight=1)
Since top_notebook
is in self.my_parent
you must give columns of self.my_parent
weight if you want the notebook to be able to fill the parent. If you want the notebook to fill all of the extra space allocated to it, you must give it the sticky
attribute:
top_notebook.grid(column = 0, row = 0, sticky="nsew")
You have another bit of misunderstanding with these lines of code:
label_one_of_nb_one_of_top.grid_columnconfigure(0, weight = 1)
...
label_one_of_nb_two_of_top.grid_columnconfigure(0, weight = 1)
...
label_one_of_nb_two_of_top.grid_columnconfigure(0, weight = 1)
...
label_two_of_nb_two_of_top.grid_columnconfigure(0, weight = 1)
What you are doing is telling grid that any extra space inside the label should be allocated to widgets in column 0 inside the label. However, there are no other widgets inside the label, so this has absolutely no effect. Remember, grid_rowconfigure
and grid_columnconfigure
only affect child widgets.
grid
is great, but it sometimes requires more work to set up. pack
is a much better choice in the case where you have a single widget inside another widget, and you want that inside widget to fill its parent. It's also good if your are arranging widgets in a single row (eg: toolbar) or column (eg: a toolbar / main work area / statusbar arranged top-to-bottom), but that's not particularly relevant to your code.
For example, each of your "top" tabs has only a single child, which is another notebook. This is a perfect place to use pack
, because you can do everything in one line of code:
# Notebook of tab one:
nb_one_of_top = ttk.Notebook(first_tab_of_top)
nb_one_of_top.pack(fill="both", expand=True)
# Notebook of tab two:
nb_two_of_top = ttk.Notebook(second_tab_of_top)
nb_two_of_top.pack(fill="both", expand=True)
To use grid properly you must give a weight to row 0 and column 0 of each tab, adding four lines of extra code.
Upvotes: 2