1

I'm building a small program where different parts of the code will call on one object different times. I'd like to try and make it call the previous frame back instead of duplicating the actual code multiple times. Here is part of my code if you need an example:

    #Console Menu
    class consoleMenu(tk.Frame):

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

            #Setups
            consoleGuideLabel = ttk.Label(self, text = "Console Guide", font = LARGE_FONT)

            consoleItemInfoButton = ttk.Button(self, text = "Console Item Info", command = lambda: controller.show_frame(consoleItemInfo))
            consoleVersionButton = ttk.Button(self, text = "Console Version History", command = lambda: popupmsg ("Not supported just yet!"))
            consoleMainMenuButton = ttk.Button(self, text = "Main Menu", command = lambda: controller.show_frame(StartPage))

            #Placement
            consoleGuideLabel.pack(pady = 10, padx = 10)

            consoleItemInfoButton.pack()
            consoleVersionButton.pack()
            consoleMainMenuButton.pack()

Now this is the part that gets called on multiple times by different frames.

    #Air - MCPE, PC, Xbox
    class mc_air(tk.Frame):

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

            #Item Info
            text_file = open("minecraft_air.txt", "r")
            file = text_file.read()
            text_file.close()

            #Setups
            airLabel = ttk.Label(self, text = "Minecraft - Air - 1", font = LARGE_FONT)
            airInfo = ttk.Label(self, text = file, font = NORMAL_FONT)
            exitButton = ttk.Button(self, text = "Return to Menu", command = lambda: controller.show_frame(StartPage))

            #Placement
            airLabel.pack(pady = 10, padx = 10)
            airInfo.pack()
            exitButton.pack()

Where it says:

exitButton = ttk.Button(self, text = "Return to Menu", command = lambda:      controller.show_frame(StartPage))

I'd like to be able to replace StartPage with a command to go to the previous window.

Austin Hargis
  • 139
  • 1
  • 1
  • 12

1 Answers1

0

Here is one possible implementation, based on my implementation of frame switching here:

import Tkinter as tk

class BaseFrame(tk.Frame):
    """An abstract base class for the frames that sit inside PythonGUI.

    Args:
      master (tk.Frame): The parent widget.
      controller (PythonGUI): The controlling Tk object.

    Attributes:
      controller (PythonGUI): The controlling Tk object.

    """

    def __init__(self, master, controller):
        tk.Frame.__init__(self, master)
        self.controller = controller
        self.grid()
        self.create_widgets()

    def create_widgets(self):
        """Create the widgets for the frame."""
        raise NotImplementedError

    def goto_three(self):
        self.controller.frames[FrameThree].return_to(self.__class__)
        self.controller.show_frame(FrameThree)


class FrameOne(BaseFrame):
    """First page."""

    def create_widgets(self):
        """Create the base widgets for the frame."""
        self.button_two = tk.Button(self,
                                    anchor=tk.W,
                                    command=lambda: self.controller.show_frame(FrameTwo),
                                    padx=5,
                                    pady=5,
                                    text="Two")
        self.button_two.grid(padx=5, pady=5, sticky=tk.W+tk.E)
        self.button_three = tk.Button(self,
                                      anchor=tk.W,
                                      command=self.goto_three,
                                      padx=5,
                                      pady=5,
                                      text="Three")
        self.button_three.grid(padx=5, pady=5, sticky=tk.W+tk.E)


class FrameTwo(BaseFrame):
    """Second page."""

    def create_widgets(self):
        """Create the base widgets for the frame."""
        self.button_one = tk.Button(self,
                                    anchor=tk.W,
                                    command=lambda: self.controller.show_frame(FrameOne),
                                    padx=5,
                                    pady=5,
                                    text="One")
        self.button_one.grid(padx=5, pady=5, sticky=tk.W+tk.E)
        self.button_three = tk.Button(self,
                                      anchor=tk.W,
                                      command=self.goto_three,
                                      padx=5,
                                      pady=5,
                                      text="Three")
        self.button_three.grid(padx=5, pady=5, sticky=tk.W+tk.E)


class FrameThree(BaseFrame):
    """Third page."""

    def create_widgets(self):
        """Create the base widgets for the frame."""
        self.button_two = tk.Button(self,
                                    anchor=tk.W,
                                    command=lambda: self.controller.show_frame(FrameTwo),
                                    padx=5,
                                    pady=5,
                                    text="Two")
        self.button_two.grid(padx=5, pady=5, sticky=tk.W+tk.E)
        self.button_one = tk.Button(self,
                                    anchor=tk.W,
                                    command=lambda: self.controller.show_frame(FrameOne),
                                    padx=5,
                                    pady=5,
                                    text="One")
        self.button_one.grid(padx=5, pady=5, sticky=tk.W+tk.E)
        self.button_back = tk.Button(self,
                                     anchor=tk.W,
                                     padx=5,
                                     pady=5,
                                     text="Back")
        self.button_back.grid(padx=5, pady=5, sticky=tk.W+tk.E)

    def return_to(self, frame):
        self.button_back.config(command=lambda: self.controller.show_frame(frame))


class PythonGUI(tk.Tk):
    """The main window of the GUI.

    Attributes:
      container (tk.Frame): The frame container for the sub-frames.
      frames (dict of tk.Frame): The available sub-frames.

    """

    def __init__(self):
        tk.Tk.__init__(self)
        self.title("Python GUI")
        self.create_widgets()
        self.resizable(0, 0)

    def create_widgets(self):
        """Create the widgets for the frame."""             
        #   Frame Container
        self.container = tk.Frame(self)
        self.container.grid(row=0, column=0, sticky=tk.W+tk.E)

        #   Frames
        self.frames = {}
        for f in (FrameOne, FrameTwo, FrameThree): # defined subclasses of BaseFrame
            frame = f(self.container, self)
            frame.grid(row=2, column=2, sticky=tk.NW+tk.SE)
            self.frames[f] = frame
        self.show_frame(FrameOne)

    def show_frame(self, cls):
        """Show the specified frame.

        Args:
          cls (tk.Frame): The class of the frame to show. 

        """
        self.frames[cls].tkraise()

if __name__ == "__main__":
    app = PythonGUI()
    app.mainloop()
    exit()

It's a bit hacky as it stands, but basically the idea is that goto_three calls the FrameThree instance's return_to, which alters the command on its button_back to return to whichever frame it was called from.

Community
  • 1
  • 1
jonrsharpe
  • 115,751
  • 26
  • 228
  • 437