0

I'm new to Tkinter and python. I'm following Switch between two frames in tkinter to see switch frames and it worked. Next, I'm trying to write the code for switch frames inside Page One, but I don't have any idea how to do it.

Below is the code:

from tkinter import *
import tkinter as tk
from tkinter import font as tkfont

class SampleApp(tk.Tk):

    def __init__(self, *args, **kwargs):
        tk.Tk.__init__(self, *args, **kwargs)

        self.title_font = tkfont.Font(family='Helvetica', size=18, weight="bold", slant="italic")

        # the container is where we'll stack a bunch of frames
        # on top of each other, then the one we want visible
        # will be raised above the others
        container = tk.Frame(self)
        container.pack(side="top", fill="both", expand=True)
        container.grid_rowconfigure(0, weight=1)
        container.grid_columnconfigure(0, weight=1)

        width = 1350  # 1280
        height = 720
        screen_width = self.winfo_screenwidth()
        screen_height = self.winfo_screenheight()
        x = (screen_width / 2) - (width / 2)
        y = (screen_height / 2) - (height / 2)
        self.geometry(f'{width}x{height}+{int(x)}+{int(y)}')
        self.resizable(False,False)

        self.frames = {}
        for F in (StartPage, PageOne):
            page_name = F.__name__
            frame = F(parent=container, controller=self)
            self.frames[page_name] = frame

            # put all of the pages in the same location;
            # the one on the top of the stacking order
            # will be the one that is visible.
            frame.grid(row=0, column=0, sticky="nsew")

        self.show_frame("StartPage")

    def show_frame(self, page_name):
        '''Show a frame for the given page name'''
        frame = self.frames[page_name]
        frame.tkraise()


class StartPage(tk.Frame):

    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        self.controller = controller
        label = tk.Label(self, text="This is the start page", font=controller.title_font)
        label.pack(side="top", fill="x", pady=10)

        button1 = tk.Button(self, text="Go to Page One",command=lambda: controller.show_frame("PageOne"))         
        button1.pack()
        


class PageOne(tk.Frame):

    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        self.controller = controller

        LeftFrame=tk.Frame(self,relief=RIDGE, bd=2)
        LeftFrame.place(x=0,y=0,width=160,height=720)

        button = tk.Button(LeftFrame, text="Go to the start page",font=("bold"),command=lambda: controller.show_frame("StartPage")) 
        button.grid(row=0)

        buttonBlue = tk.Button(LeftFrame, text="Go to the blue page",bg="blue",fg="white",command=self.blue,activebackground="blue",activeforeground="white")                   
        buttonBlue.grid(row=1)

        buttonRed = tk.Button(LeftFrame, text="Go to the red page",bg="red",fg="white",command=self.red,activebackground="red",activeforeground="white")                  
        buttonRed.grid(row=2)

        buttonYellow = tk.Button(LeftFrame, text="Go to the yellow page",bg="yellow",fg="black",command=self.yellow,activebackground="yellow",activeforeground="black")
        buttonYellow.grid(row=3)

    def blue(self):
        # self.hide_all_frames()
        blueFrame=tk.Frame(self,relief=RIDGE,bd=1 ,bg="blue")
        blueFrame.place(x=160,y=0,width=1190,height=720)

    def red(self):  # Do I need to put self here? It still worked without putting self here
        # self.hide_all_frames()
        redFrame=tk.Frame(self,relief=RIDGE,bd=1 ,bg="red")
        redFrame.place(x=200,y=0,width=1150,height=720)

    def yellow(self):
        # self.hide_all_frames()
        yellowFrame=tk.Frame(self,relief=RIDGE,bd=1 ,bg="yellow")
        yellowFrame.place(x=240,y=0,width=1110,height=720)

    def hide_all_frames(self):
        self.blue.withdraw()


if __name__ == "__main__":
    app = SampleApp()
    app.mainloop()

When I switch to Page One, I create a couple of buttons to switch color frames. They all overlap every time I switch between colors like the image below. overlap frames

I'm finding a way to switch color frames without overlapping each other. And, when I go back to the Start Page, all color frames should be destroyed/hidden. Please help me. Thank you so much.

Cristian
  • 155
  • 8
  • Actually you are not *switching frame* but *creating new frame* whenever those `Go to the page` buttons are clicked. – acw1668 Mar 08 '22 at 08:16
  • Yeah. Switching frames need functionality, but my knowledge of Tkinter is limit. – Cristian Mar 08 '22 at 08:21
  • Elaborate more on *"switch color frames without overlapping each other"*. What do you expect to see actually? – acw1668 Mar 08 '22 at 08:28
  • I make an assumption that I’m on Page One. When I click red button, the frame of red color background (red frame) will show. If I click blue button, the red frame is hidden and the frame of blue background color is shown. The same to yellow frame. – Cristian Mar 08 '22 at 15:44

1 Answers1

0

For the frame switching inside PageOne, you need to hide the current frame before showing the requested frame. Also it is better to create the three color frames in the __init__() and show it in the corresponding function:

class PageOne(tk.Frame):
    def __init__(self, parent, controller):
        ...

        # create the three color frames with initially hidden
        self.blueFrame = tk.Frame(self, relief=RIDGE, bd=1, bg="blue")
        self.redFrame = tk.Frame(self, relief=RIDGE, bd=1, bg="red")
        self.yellowFrame = tk.Frame(self, relief=RIDGE, bd=1, bg="yellow")

    def blue(self):
        self.hide_all_frames()
        self.blueFrame.place(x=160, y=0, width=1190, height=720)

    def red(self):
        self.hide_all_frames()
        self.redFrame.place(x=200, y=0, width=1150, height=720)

    def yellow(self):
        self.hide_all_frames()
        self.yellowFrame.place(x=240, y=0, width=1110, height=720)

    def hide_all_frames(self, event=None):
        self.redFrame.place_forget()
        self.blueFrame.place_forget()
        self.yellowFrame.place_forget()

If you want to hide all color frames after switching frames, i.e. PageOne -> MainPage -> PageOne, you can notify the PageOne using virtual event when it is raised. Then PageOne hides all the color frames upon receiving such virtual event:

class SampleApp(tk.Tk):
    ...

    def show_frame(self, page_name):
        '''Show a frame for the given page name'''
        frame = self.frames[page_name]
        frame.tkraise()
        # notify the raised frame via virtual event
        frame.event_generate('<<Raised>>') 

...

class PageOne(tk.Frame):
    def __init__(self, parent, controller):
        ...

        self.blueFrame = tk.Frame(self, relief=RIDGE, bd=1, bg="blue")
        self.redFrame = tk.Frame(self, relief=RIDGE, bd=1, bg="red")
        self.yellowFrame = tk.Frame(self, relief=RIDGE, bd=1, bg="yellow")

        self.bind('<<Raised>>', self.hide_all_frames)
acw1668
  • 40,144
  • 5
  • 22
  • 34