Skip to content

Instantly share code, notes, and snippets.

@Stevoisiak
Created September 24, 2018 16:55
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Stevoisiak/c38a35366ac0b035009ed5e284629da0 to your computer and use it in GitHub Desktop.
Save Stevoisiak/c38a35366ac0b035009ed5e284629da0 to your computer and use it in GitHub Desktop.

Switching frames in tkinter by passing class objects

A question on Stack Overflow asked how to create a tkinter GUI in Python 3 that would switch between two frames: A start-page and a sub-page.

Objectives

  • Create a Python 3 app which switches between multiple tkinter frames
  • Code should be readable and easy to understand
  • Scaleable to larger apps where classes are split across multiple files

My Approach

I answered with a sample app that switches between a main page and two sub-pages. The concept is, have a parent Tk class (master) with a switch_frame() method. When called with a frame class, this method will create a new frame to replace the old one.

Code

# Multi-frame tkinter application v2.3
import tkinter as tk

class SampleApp(tk.Tk):
    def __init__(self):
        tk.Tk.__init__(self)
        self._frame = None
        self.switch_frame(StartPage)

    def switch_frame(self, frame_class):
        """Destroys current frame and replaces it with a new one."""
        new_frame = frame_class(self)
        if self._frame is not None:
            self._frame.destroy()
        self._frame = new_frame
        self._frame.pack()

class StartPage(tk.Frame):
    def __init__(self, master):
        tk.Frame.__init__(self, master)
        tk.Label(self, text="This is the start page").pack(side="top", fill="x", pady=10)
        tk.Button(self, text="Open page one",
                  command=lambda: master.switch_frame(PageOne)).pack()
        tk.Button(self, text="Open page two",
                  command=lambda: master.switch_frame(PageTwo)).pack()

class PageOne(tk.Frame):
    def __init__(self, master):
        tk.Frame.__init__(self, master)
        tk.Label(self, text="This is page one").pack(side="top", fill="x", pady=10)
        tk.Button(self, text="Return to start page",
                  command=lambda: master.switch_frame(StartPage)).pack()

class PageTwo(tk.Frame):
    def __init__(self, master):
        tk.Frame.__init__(self, master)
        tk.Label(self, text="This is page two").pack(side="top", fill="x", pady=10)
        tk.Button(self, text="Return to start page",
                  command=lambda: master.switch_frame(StartPage)).pack()

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

Start page Page one Page two

While this small example works, I'm concerned this approach could result in circular references if scaled to a larger application with multiple files. (eg: StartPage imports PageOne, PageOne imports StartPage, and so on). I'm also unsure if my example is simple enough, or if it could be simplified further.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment