Py_Rog
Py_Rog

Reputation: 45

positioning of a 3 Frames layout with tkinter

I'm re-doing from scratch a GUI for a program beacuse I realise that a new layout would make it easier to use but I'm getting very confused. I've been looking for scripts resulting in similar layout, but the more I read about it, the less I understand. The image below is the very basic structure of the GUI that I'm trying to make:

enter image description here

I'm aware that it is a very simple question, but the docs and previous questions are not making the understading process any easier. I believe that having just the code of the main layout would be a huge help to finally understand how to organise frames.

NOTE: The background color and text are there just to make the layout more clear. I'm only asking for the very basic frame's arrangement.

As always, thanks a lot to anyone who help. Cheers

Upvotes: 1

Views: 2126

Answers (1)

Bryan Oakley
Bryan Oakley

Reputation: 385890

You can use pack, place, or grid. They all can produce this layout, though I personally recommend not using grid.

For me, pack is the natural choice. pack excels at layouts where widgets take up an entire side of a region. If that fits your design, pack requires fewer lines of code than grid, and fewer and less confusing options than place.

In this specific case the blue area clearly takes up the whole left side, and the yellow and red fill up the top and bottom of the right side, so pack is well suited to the task.

For the following examples, we'll start with this code:

import tkinter as tk

root = tk.Tk()

f1 = tk.Frame(root, bg='blue', width=200,height=400)
f2 = tk.Frame(root, bg='yellow', width=400, height=300)
f3 = tk.Frame(root, bg='red', width=400, height=100)

do_layout()

root.mainloop()

Using pack

pack works by placing widgets along a side of an empty area. In this case, the blue area is clearly taking up the left side. In the space that remains after adding the blue area, the yellow space takes up the top part of the remaining space and the red area takes the bottom.

def do_layout():
    f1.pack(side="left", fill="both", expand=True)
    f2.pack(side="top", fill="both", expand=True)
    f3.pack(side="bottom", fill="both", expand=True)

Whether this is what you actually want or not is hard to say. It depends a lot on how you want the widgets to react when you add children or you resize the window. You may want to change the expand and/or fill options for some of the windows, though that depends on how you want the widgets to react when the user resizes the window.

Using grid

Grid is often the easiest technique to grasp. You specify positions within a row or column, and can decide if an item should span one or more rows or column.

In your case you clearly have two rows and two columns, and the blue area spans both rows.

def do_layout():
    f1.grid(row=0, column=0, rowspan=2, sticky="nsew")
    f2.grid(row=0, column=1, sticky="nsew")
    f3.grid(row=1, column=1, sticky="nsew")

    root.grid_rowconfigure(0, weight=1)
    root.grid_columnconfigure(1, weight=1)

Like with the pack example, it's hard to say if this meets your actual needs. Again, it depends on how you want the UI to behave when you add widgets to the frames and when you resize the window.

Notice that grid requires a couple of extra lines of code. As a general rule of thumb you should always give at least one row and one column a non-default weight so that grid knows what to do with unallocated space.

Using place

place is arguably the weakest choice of the three for this type of layout. Nevertheless, you can achieve the same result as with the others.

def do_layout():
    f1.place(x=0, y=0, relwidth=.3, relheight=1.0)
    f2.place(relx=.3, y=0, relwidth=.7, relheight=.6)
    f3.place(relx=.3, rely=.6, relwidth=.7, relheight=.4)

One of the significant differences between place and the other options is that the use of place will not cause the containing window to grow or shrink to fit contents. You are required to make sure that the containing widget (in this case, root) is the correct size.

Other options

Another option would be to use a paned widget, in the case where you want the user to be able to adjust the proportions of an area. For example, you could use a horizontal paned widget to allow the user to make the blue area widget or narrower. Likewise, you could use a vertical paned window if you want the user to be able to adjust the relative height of each area.

You can also mix and match. While you can't use both grid and pack directly within the root window, you could use pack to lay out a frame on the left and a frame on the right, and then use grid within the right to lay out one frame on top and one on bottom. Or visa versa.

Upvotes: 1

Related Questions