Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
206 views
in Technique[技术] by (71.8m points)

python - Tkinter pack method confusion

I cant understand why the pack manager wont let you pack LEFT AND RIGHT below top packed widgets. My expected output of the following code would be

 A
 B
C D 
 E

But instead it only shows:

 A
 B
C D
import tkinter as tk

root = tk.Tk()
w, h = root.winfo_screenwidth(), root.winfo_screenheight()
root.state('zoomed')
root.geometry("%dx%d+0+0" % (w-15, h-75))
A = tk.LabelFrame(root,text='A', bd=2)
B = tk.LabelFrame(root,text='B', bd=2)
C = tk.LabelFrame(root,text='C', bd=2)
D = tk.LabelFrame(root,text='D', bd=2)
E = tk.LabelFrame(root,text='E', bd=2)

A.pack(fill=tk.BOTH, expand=tk.TRUE)
B.pack(fill=tk.BOTH, expand=tk.TRUE)
C.pack(side=tk.LEFT,fill=tk.BOTH, expand=tk.TRUE)
D.pack(side=tk.RIGHT,fill=tk.BOTH, expand=tk.TRUE)
E.pack(side=tk.BOTTOM, fill=tk.BOTH, expand=tk.TRUE)

root.mainloop()
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

In short, the packer isn't designed to directly create the layout you're trying to create. You can do it, but it requires some extra frames. In this particular case where you're clearly trying to create a grid, grid is arguably the better choice.

Before I get to an explanation for why this is so, let me suggest a solution. Create another frame called "CD" which will be used to hold both C and D. You can then pack C to the left and D to the right, and then place this frame below B. That is how you achieve the desired result using the packer.

A = tk.LabelFrame(root,text='A', bd=2)
B = tk.LabelFrame(root,text='B', bd=2)
CD = tk.Frame(root)
C = tk.LabelFrame(CD,text='C', bd=2)
D = tk.LabelFrame(CD,text='D', bd=2)
E = tk.LabelFrame(root,text='E', bd=2)

C.pack(side=tk.LEFT,fill=tk.BOTH, expand=tk.TRUE)
D.pack(side=tk.RIGHT,fill=tk.BOTH, expand=tk.TRUE)

A.pack(fill=tk.BOTH, expand=tk.TRUE)
B.pack(fill=tk.BOTH, expand=tk.TRUE)
CD.pack(fill=tk.BOTH, expand=tk.TRUE)
E.pack(side=tk.BOTTOM, fill=tk.BOTH, expand=tk.TRUE)

Explaining the packer

The packer works by reserving a parcel of space along the side of unallocated space. This allocated space takes up the full width of the unallocated space when packing the widget to the top or bottom, and takes up the full height when packing on the left or right. This is an important detail.

Let me try to describe it with some screenshots. In all cases, the following screenshots do not show the frames, they show the amount of allocated and unallocated space being managed by the packer.

When you pack A along the top (top is the default if you don't specify a side), a parcel of space is reserved for the full width of the root window. And because you packed it to the top, the only remaining space is below A. Nothing can be packed to the left or right of A from this point on.

(Actually, you can put things to the left or right by using some advanced options, but that's beyond the scope of this description)

available space after A

When you pack B along the top, the only available space is below A. Again, because you packed it along the top, after packing B the only available free space now will be below B.

available space after B

When you pack C along the left, a parcel of space is reserved for the full height of the remaining space. That means nothing will be able to be placed below C. All of the remaining space is to the right of C, and below B.

available space after C

  1. When you pack D, it must go to the right of C and below B. Because you pack it to the right, it will reserve all remaining vertical space above and below D.

available space after D

When you pack E along the bottom, the only place it can go is below B, to the right of C, and to the left of D.

available space after E

Because of the nature of the packer allocating all space along a side, the packer works best when all widgets are placed on the same axis - either stacked vertically or horizontally. When you want to switch the axis as you did with C and D, its usually best to put them in side a separate frame. Within that frame you can put widgets left-to-right, but the frame can remain in the top-to-bottom axis as the other widgets.

Note: this is what is actually happening in your code: E is being squeezed between C and D. It's not visible for various reasons, but if you were to give it an explicit size and color then it would show up.

For more information

The authoritative description of the packer algorithm can be found in the tcl/tk man pages for pack.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

2.1m questions

2.1m answers

60 comments

57.0k users

...