2

I am currently working on a GUI where I want my GUI to stay 5 seconds on the last frame, and then come back from the last frame to the first frame without any interaction.

If I use the after widget method, then the timer starts from the beginning of the application. If I put it inside a method, and if I call that method, the same behaviour ocurs. On the other hand, if I call that function through a button, it works as expected.

Controller

# The code for changing pages was derived from:
  http://stackoverflow.com/questions/7546050/switch-between-two-frames-in-tkinter
# License: http://creativecommons.org/licenses/by-sa/3.0/   

import tkinter as tk


LARGE_FONT= ("Verdana", 12)


class SeaofBTCapp(tk.Tk):

    def __init__(self, *args, **kwargs):

        tk.Tk.__init__(self, *args, **kwargs)
        container = tk.Frame(self)

        container.pack(side="top", fill="both", expand = True)

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

        self.frames = {}

        for F in (StartPage, PageOne, PageTwo):

            frame = F(container, self)

            self.frames[F] = frame

            frame.grid(row=0, column=0, sticky="nsew")

        self.show_frame(StartPage)

    def show_frame(self, cont):

        frame = self.frames[cont]
        frame.tkraise()

StartPage class

class StartPage(tk.Frame):

    def __init__(self, parent, controller):
        tk.Frame.__init__(self,parent)
        label = tk.Label(self, text="Start Page", font=LARGE_FONT)
        label.pack(pady=10,padx=10)

        button = tk.Button(self, text="Visit Page 1",
                        command=lambda: controller.show_frame(PageOne))
        button.pack()

        button2 = tk.Button(self, text="Visit Page 2",
                        command=lambda: controller.show_frame(PageTwo))
        button2.pack()

PageOne class

class PageOne(tk.Frame):

    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        label = tk.Label(self, text="Page One!!!", font=LARGE_FONT)
        label.pack(pady=10,padx=10)

        button1 = tk.Button(self, text="Back to Home",
                        command=lambda: controller.show_frame(StartPage))
        button1.pack()

        button2 = tk.Button(self, text="Page Two",
                        command=lambda: controller.show_frame(PageTwo))
        button2.pack()

PageTwo class

class PageTwo(tk.Frame):

    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        label = tk.Label(self, text="Page Two!!!", font=LARGE_FONT)
        label.pack(pady=10,padx=10)

        button1 = tk.Button(self, text="Back to Home",
                        command=lambda:self.start_reset())
        button1.pack()

        button2 = tk.Button(self, text="Page One",
                        command=lambda: controller.show_frame(PageOne))
        button2.pack()
        # self.after(5000,self.controller.show_frame(StartPage)) works only
        # once and the time starts from the start of the GUI and after 5000ms it takes
        # the gui to the start page no matter what  
    def start_reset(self):
        self.after(5000,self.controller.show_frame(StartPage))


app = SeaofBTCapp()
app.mainloop()
Right leg
  • 16,080
  • 7
  • 48
  • 81
Reactive_learner
  • 417
  • 1
  • 4
  • 21
  • Related: [How to use the after method to make a periodical call?](https://stackoverflow.com/q/44085554/7051394) – Right leg Sep 05 '17 at 08:33

1 Answers1

4

There are several place where you can put your call to the after method. To me, it makes more sense if it's placed in the controller class, because it is meant to manage the components.

One direct way to achieve this is to complete the SeaofBTCapp.show_frame method:

def show_frame(self, cont):
    frame = self.frames[cont]
    frame.tkraise()

    if cont == PageTwo:
        self.after(5000, self.show_frame, StartPage)

When the show_frame method is called, a call to show_frame with StartPage as parameter is scheduled.

Right leg
  • 16,080
  • 7
  • 48
  • 81