1

I'm having an extremely difficult time understanding Python grid layouts with tkinter. Here is a layout I'm trying to understand how to create.

Layout

From what I understand I would create 8 frames. The top frame would include the top 3 frames and would have a row of 0 and columnspan of 3. The bottom frame would include the bottom 3 frames and would have a row of 1 and columnspan of 3. One thing I don't understand is how the sticky attribute works and plays a part in this. Another thing I don't understand is the weight in grid_rowconfigure/columnconfigure. From what I see it's supposed to grow each frame at a different rate? The higher the weight the smaller it will be compared to the smaller numbers (i.e. weight of 1 with a weight of 3 on another frame means that the 3 will grow at 1/3 the size of the 1). The widgets on ctrleft frame seem like I could set them in place by just using pack to make a straight line and changing the padding. Am I wrong on this? Thanks in advance to anyone that takes the time to help.

  • [Can you provide us with your script?](https://stackoverflow.com/help/mcve) – Xantium Nov 23 '17 at 13:53
  • None of these questions can't be self answered by simple trial and error. Try something, if it looks different than what you've expected, and you can't tell why, _then_ post a question here please. – Nae Nov 23 '17 at 13:53

1 Answers1

4

There are many ways to accomplish your task. The important thing is to not try to solve all layout problems at once. You need to take a "divide and conquer" approach. Break the UI into logical groups, arrange the groups, and then break each group into smaller groups and arrange them, and so on.

For example, here's how I might do this particular arrangement:

I would start by creating six functions (or six classes, if you prefer), one for each major section. The main part of the gui code when then look something like this:

class Example(object):
    def __init__(self):
        root = tk.Tk()
        topleft = self.create_topleft()
        topmid = self.create_topmid()
        ...

The logical arrangement seems to be a 2x3 grid. Assuming you want every section to expand equally when you resize the window, I could give all rows and all columns all an identical weight so that extra space is equally divided among the rows and columns:

class Example(object):
    def __init__(self):
        ...
        root.grid_rowconfigure(0, weight=1)
        root.grid_rowconfigure(1, weight=1)
        root.grid_columnconfigure(0, weight=1)
        root.grid_columnconfigure(0, weight=1)
        root.grid_columnconfigure(1, weight=1)

Finally, I would lay the widgets out in the grid:

class Example(object):
    def __init__(self):
        ...
        topleft.grid(row=0, column=0, sticky="nsew")
        topmid.grid(row=0, column=1, sticky="nsew")
        ...

With that, the general structure of your UI is set. You can even test resize behavior without adding any of the other widgets. Give each of the sections a distinct color and a temporary size, and then experiment by resizing the window to see how each section responds.

You can now develop each section independently, without worrying very much about how they affect the rest of the GUI. For example, the widgets inside some sections could use pack, some could use grid, and you could even use place if that made the most sense.

for example, ctrmid seems perfect for pack since you have one large widget on top, and a smaller one on bottom.

ctrleft would itself looks like it's two labels plus an inner frame. These could be arranged with pack, but the the widgets inside the inner frame could use grid to form the table.

Another thing I don't understand is the weight in grid_rowconfigure/columnconfigure. ...(i.e. weight of 1 with a weight of 3 on another frame means that the 3 will grow at 1/3 the size of the 1).

You have that backwards. The weight describes how extra space is allocated, and the weights are proportional. A weight of 2 means that the row or column will get twice as much extra space as a column with a weight of 1.

Bryan Oakley
  • 370,779
  • 53
  • 539
  • 685