Omitting the basics of what each of these objects means (plenty of information in the web), will compile some tricks to go beyond simple layouts with tkinter.

Layout management

You cannot mixed different managers in the same container. You’ll get the famous error

_tkinter.TclError: cannot use geometry manager grid inside . which already has slaves managed by pack

If the GUI you are creating requires a combination of these (e.g. displaying dataframes), the solution is using containers such as frames or canvas. Use pack to organize the containers inside the same window and then use grid (or any other) inside each container:

import tkinter as tk
parent = tk.Tk()
frame = tk.Frame(parent)frame.pack()
tk.Label(parent, text='label1').pack()
tk.Label(frame, text='label2').grid(row=0, column=0)
tk.Label(frame, text='label3').grid(row=0, column=1)
parent.mainloop() 

Result:

Scrolling

If you need scrolling for viewing multiple objects, a frame won’t work as it doesn’t support scrolling. One of the alternatives is to use the object canvas and insert a frame with the widgets you want on it:

import tkinter as tk
parent = tk.Tk()
frame = tk.Frame(parent)
frame.pack()
canvas = tk.Canvas(frame)
scrolly = tk.Scrollbar(frame, orient="vertical", command=canvas.yview)
frameCanvas = tk.Frame(canvas)
for i in range(20):
    tk.Label(frameCanvas, text='label %i' % i).pack()
canvas.create_window(0, 0, anchor='nw', window=frameCanvas)
canvas.configure(scrollregion=(0,0,100,500), yscrollcommand=scrolly.set)
canvas.pack(side='left')
scrolly.pack(fill='y', side='right')
parent.mainloop() 

Result:

Notice how the scroll region does not accurately match the position of the inner widgets. To get actual box size of the canvas, the canvas method bbox can be used. However remember to always update the canvas, otherwise you will get the size of the canvas when it was created:

...
canvas.create_window(0, 0, anchor='nw', window=frameCanvas)
canvas.update()
canvas.config(scrollregion=canvas.bbox('all'), yscrollcommand=scrolly.set)
canvas.pack(side='left')
scrolly.pack(fill='y', side='right')               
parent.mainloop() 

Result:

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s