Josh Josh - 1 month ago 11
Python Question

Displaying only one frame at a time in tkinter

I've been struggling with this for a while. I think I'm missing some simple piece of information and I hope you guys can help clear this up for me.

I'm trying to get tkinter to display different frames which I will eventually place widgets inside of. Here's what I did:


  1. I've made a class that is supposed to initialize the window and make all the different frames the program will run.

  2. I've made a separate class for each frame(I'm intending to have variables associated with the different classes when the program is done), and assigned a variable that will start that class up and make it run it's init function

  3. I ended the StartUp class by telling it to tkraise() the frame I want displayed, and that's where things stop working correctly.



I set each frame to a different color, so when you run this program you will see that they split the screen space up instead of one being raised to the top. What am I missing?

One last point, I am purposely trying to spell everything out in my program, I learn better that way. I left it so I have to type tkinter.blah-blah-blah in front of each tkinter command so I can recognize them easily, and I decided not to have my classes inherit Frame or Tk or anything. I'm trying to understand what I'm doing.

import tkinter

class StartUp:
def __init__(self):
self.root = tkinter.Tk()
self.root.geometry('300x300')

self.container = tkinter.Frame(master=self.root, bg='blue')
self.container.pack(side='top', fill='both', expand=True)

self.page1 = Page1(self)
self.page2 = Page2(self)

self.page1.main_frame.tkraise()


class Page1():
def __init__(self, parent):
self.main_frame = tkinter.Frame(master=parent.container, bg='green')
self.main_frame.pack(side='top', fill='both', expand=True)


class Page2():
def __init__(self, parent):
self.main_frame = tkinter.Frame(master=parent.container, bg='yellow')
self.main_frame.pack(side='top', fill='both', expand=True)


boot_up = StartUp()
boot_up.root.mainloop()

Answer

When you do pack(side='top', ...), top doesn't refer to the top of the containing widget, it refers to the top of any empty space in the containing widget. Page initially takes up all of the space, and then when you pack Page2, it goes below Page1 rather than being layered on top of it.

If you are using the strategy of raising one window above another, you need to either use grid or place to layer the widgets on top of each other. The layering is something pack simply can't do.

Your other choice is to call pack_forget on the current window before calling pack on the new windowl