For the sake of completeness, here is how to have the two option-menus side by side in the upper center of the window , even after resizing it, with the three possible layout:
1) With grid
:
This layout puts widgets in cells defined by the row and column numbers.
import Tkinter as tk # python 2
# from tkinter import tk # python 3
class MyOptionMenu(tk.OptionMenu):
def __init__(self, master, status, *options):
self.var = tk.StringVar(master)
self.var.set(status)
tk.OptionMenu.__init__(self, master, self.var, *options)
self.config(font=('calibri',(10)),bg='white',width=12)
self['menu'].config(font=('calibri',(10)),bg='white')
root = tk.Tk()
root.columnconfigure(0, weight=1)
root.columnconfigure(1, weight=1)
mymenu1 = MyOptionMenu(root, 'Select status', 'a','b','c')
mymenu2 = MyOptionMenu(root, 'Select another status', 'd','e','f')
mymenu1.grid(row=0, column=0, sticky='e')
mymenu2.grid(row=0, column=1, sticky='w')
root.mainloop()
The two key elements in the code are:
root.columnconfigure(<column number>, weight=1)
: by default, the column weight is 0, so it does not expand to fill the window. You can set this to any integer. For instance if you have two columns, one with weight 1 and the other with weight 2, then the second one will take twice as much space as the first.
the sticky
option in .grid()
: it can be any combination of the cardinal points n
, s
, e
, w
. For instance, sticky='e'
means that the widget will be on the east side of the grid cell and sticky='ew'
means that it will fill the column horizontally.
2) With pack
:
pack
stacks widgets starting from the side given in option, so there is no direct way to get both widgets side by side at the upper center of the window. However this can be done using a frame container:
import Tkinter as tk
class MyOptionMenu(tk.OptionMenu):
def __init__(self, master, status, *options):
self.var = tk.StringVar(master)
self.var.set(status)
tk.OptionMenu.__init__(self, master, self.var, *options)
self.config(font=('calibri',(10)),bg='white',width=12)
self['menu'].config(font=('calibri',(10)),bg='white')
root = tk.Tk()
frame = tk.Frame(root) # container
mymenu1 = MyOptionMenu(frame, 'Select status', 'a','b','c')
mymenu2 = MyOptionMenu(frame, 'Select another status', 'd','e','f')
mymenu1.pack(side='left')
mymenu2.pack(side='left')
frame.pack()
root.mainloop()
By default, the side
option o .pack()
is 'top'
, so frame
is put at the upper center of the window. But to have the option-menus side by side in the frame, you need to use 'left'
or 'right'
.
pack
is easy to use if your layout is simple. But as soon as you want something more complicated, you need to use many frame containers to get what you want, so it is easier to use grid
instead.
3) With place
:
import Tkinter as tk
class MyOptionMenu(tk.OptionMenu):
def __init__(self, master, status, *options):
self.var = tk.StringVar(master)
self.var.set(status)
tk.OptionMenu.__init__(self, master, self.var, *options)
self.config(font=('calibri',(10)),bg='white',width=12)
self['menu'].config(font=('calibri',(10)),bg='white')
root = tk.Tk()
mymenu1 = MyOptionMenu(root, 'Select status', 'a','b','c')
mymenu2 = MyOptionMenu(root, 'Select another status', 'd','e','f')
mymenu1.place(relx=0.5, y=0, anchor='ne')
mymenu2.place(relx=0.5, y=0, anchor='nw')
root.mainloop()
.place()
can take the position of the widget either as an absolute position (in pixels, with respect to the top left corner of the container) with the options x
and y
or as a relative position with the options relx
and rely
. So, relx=0.5
means half the width of the container (in the code sample, the container is root
).
- The option
anchor
determine which part of the widget is put at the coordinates given in .place
. So widget.place(x=x, y=y, anchor='nw')
will place the top left corner of the widget at position (x, y).
With place
, the widget can be put in an arbitrary position, but you have to handle manually the overlapping issues while pack
and grid
handle overlapping automatically.