Python Forum
[Tkinter] grid layout
Thread Rating:
  • 1 Vote(s) - 2 Average
  • 1
  • 2
  • 3
  • 4
  • 5
[Tkinter] grid layout
#1
I would like to be consistent in my window management (I heard that was best practice). However, I have a window that is 800x400 which is the size of my touch screen and I can't get the page objects to fill the window. Any help is very much appreciated.

Thanks,
neech
Reply
#2
Update. I found another issue, when I add widgets to the page(s) class they don't overlap each other anymore.

Reply
#3
grid is a funny geometry. If you plan out your screen on a grid, it works well. It tends to be quite finicky.
to fill a frame, use

yourwidget.grid(..., sticky='nsew', ...)
in order to place your widgets properly, it's real important to know exactly how many columns you are going to use,
and to set the columns correctly. Also, it's good to use an odd number so you need to center.
It's next to impossible to get it right if you don't draw it out first using a 'Grid form' with row and columns marked.

I highly recommend looking at the book 'Python and Tkinter Programming' by John Grayson. This is an old book,
and actually went out of print, but it is so full of extremely valuable information that a new printing has been done.
(publisher Manning)

You can get a used version on amazon very inexpensively, and most if not all is on line, albeit copyright issues may apply.

Page 87 shows the perfect GUI layout form.

I was just playing around with this a little. You're grid rows and columns are too confusing.
Do you have a drawing showing row and column layout of each window?
It would be very helpful.
Reply
#4
@Larz60, thank you for the reply. I will try and pick up that book you suggested. Here's the deal with my layout. I was hoping I could have nested grids inside frames with Tkinter. The image below shows what I am after. I will put more widgets inside the nested frames but I just wanted you to get the idea. The buttons on the left side toggle between pages (nested frames on right side). I need the nested frames to take up the whole space because when they lift on top of each other I don't want anything on the other pages (frames) to be visible. Make sense? The black boxes are buttons. Grid 1 will have 2 columns and 6 rows; grid 2 will have 4 rows and 5 columns.
[Image: ivxHOA7.png]
Reply
#5
Sorry, I totally forgot about your post, and thought someone else might have responded.
Nevertheless, I'm back. I thought your original post had code with it, but I don't see any. You will need Python 3
or do the conversion to Python 2 yourself, in order to complete the task.


I'll try to get what you're looking for.

first, Inside your root window you are going to make two frames, one for the buttons on the left,

and one to fill the entire area that gets overlaid on the right. These wukk use the pack geometry

Inside the left frame, you will layout your buttons using grid. Since they are encapsulated inside of
the frame that was made, each button will span two rows, and contain padding on both the x and y axis
to make them appear as though they are floating.


within the second frame, I'd use a tkinter.ttk Notebook widget without tabs (since the buttons will replace the tabs.
This will allow you to overlay that frame by simply switching tabs. the layout for each tab can be completely different
from one another, you can make some canvases, text windows, data entry, or whatever. The Notebook widget will make
switching windows simple.

I'll go so far as to modify your layout on a spreadsheet which I'll attach later today as soon as it is done. I'll also give
you a template with the basic frames and notebook to get you started.
Reply
#6
@Larz60+ The code in the op post has been put in to spoiler tags, click spoiler to reveal the code.
Reply
#7
Grid Layout
Reply
#8
There is currently a problem with images.
Nevertheless, I want you to see the advantage of adding row and column numbers
to a gui layout, so will still send it later.

Your page 1 and page 2 are different sizes, and that is a problem. Any overlay that
uses raise or lower must be exactly the same size.

The reason they are two sizes is the way grid geometry works. The full frame does not display unless
something within fills out the space. It has the added problem that it will grow on its own if the
space is too small.

If you use pack for the containers, and the space for it's contents is too small, the contents will get
truncated, rather than grow the container which is much better than having the container automatically change size.

For this reason, change your containers (p1 and p2) to pack geometry, and keep grid for all contents of
of these containers. Make sure you specify fill='both' and expand='True' in the pack command.

This should fix the problem.

finally got the size right
Reply
#9
Here's the template I promised:

import tkinter as tk


class GuiOverlay:
    def __init__(self, parent):

        self.f1 = tk.Frame(parent, padx=2, pady=2, relief=tk.SUNKEN)
        self.f1.pack(side='left', fill='both', expand=True)

        self.f1_widgets = list()
        self.f1_numbuttons = 8
        self.f1_row = 1
        self.f1_col = 0

        self.f2 = tk.Frame(parent, padx=2, pady=2, relief=tk.SUNKEN)
        self.f2.pack(side='right', fill='both', expand=True)

        self.f2.widgets = list()

        self.build_f1()
        self.build_page1()
        self.build_page2()
        self.build_page3()
        self.show_page(self.page1)

    def add_sep(self, r, c, widg):
        tk.Label(widg).grid(row=r, column=c)

    def build_f1(self):
        self.lf1 = tk.Label(self.f1, text='PAGE SELECT')
        self.lf1.grid(row=0, column=0)
        b1 = tk.Button(self.f1, text="Page 1", command=lambda: self.show_page(self.page1), width=8, height=2)
        b1.grid(row=1, column=0)
        b2 = tk.Button(self.f1, text="Page 2", command=lambda: self.show_page(self.page2), width=8, height=2)
        b2.grid(row=2, column=0)
        b3 = tk.Button(self.f1, text="Edit", command=lambda: self.show_page(self.page3), width=8, height=2)
        b3.grid(row=3, column=0)
        b4 = tk.Button(self.f1, text="Reserved", command=self.pass_function, width=8, height=2)
        b4.grid(row=4, column=0)
        b5 = tk.Button(self.f1, text="Reserved", command=self.pass_function, width=8, height=2)
        b5.grid(row=5, column=0)
        b6 = tk.Button(self.f1, text="Reserved", command=self.pass_function, width=8, height=2)
        b6.grid(row=6, column=0)
        b7 = tk.Button(self.f1, text="Reserved", command=self.pass_function, width=8, height=2)
        b7.grid(row=7, column=0)
        b8 = tk.Button(self.f1, text="Reserved", command=self.pass_function, width=8, height=2)
        b8.grid(row=8, column=0)

    def build_page1(self):
        self.page1 = tk.Frame(self.f2, padx=2, pady=2, relief=tk.SUNKEN)
        self.page1.grid(row=0, column=0, sticky='nsew')

        p1l1 = tk.Label(self.page1, text='This is page1')
        p1l1.grid(row=0, column=0)

        self.page1.lower()

    def build_page2(self):
        self.page2 = tk.Frame(self.f2, padx=2, pady=2, relief=tk.SUNKEN)
        self.page2.grid(row=0, column=0, sticky='nsew')

        p2l1 = tk.Label(self.page2, text='This is page2')
        p2l1.grid(row=0, column=0)

        up_button = tk.Button(self.page2, text="up")
        up_button.grid(row=1, column=0)

        temp_setpoint_label = tk.Label(self.page2, text="75")
        temp_setpoint_label.grid(row=1, column=1)

        down_button = tk.Button(self.page2, text="dn")
        down_button.grid(row=1, column=2)

        self.page2.lower()

    def build_page3(self):
        self.page3 = tk.Frame(self.f2, padx=2, pady=2, relief=tk.SUNKEN)
        self.page3.grid(row=0, column=0, sticky='nsew')

        p3l1 = tk.Label(self.page3, text='Most Excellent Edit Page')
        p3l1.grid(row=0, column=0)

        p3tx = tk.Text(self.page3)
        p3tx.grid(row=1, column=0, sticky='nsew')

        self.page2.lower()

    def show_page(self, pageno):
        pageno.lift()

    def pass_function(self):
        pass


def main():
    root = tk.Tk()
    # root.geometry("800x400")
    root.title('Try GUI overlay')
    GuiOverlay(root)
    root.mainloop()


if __name__ == '__main__':
    main()
And a screenshot
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  Using Grid layout and QHBox hobbyist 1 3,023 Jan-26-2021, 12:35 AM
Last Post: deanhystad
  pyqt5 layout Nickd12 8 3,401 Jan-18-2021, 09:09 AM
Last Post: Axel_Erfurt
  [Kivy] Weird spacing in grid layout test 3 3,402 Nov-08-2019, 04:37 PM
Last Post: Axel_Erfurt
  Python GUI layout off between different OS shift838 5 3,620 Jan-02-2019, 02:53 AM
Last Post: shift838

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020