0

so there is this stackoverflow question:

Switch between two frames in tkinter

Which looks like a beautiful basis for building an application. But what if on startPage i want to have multiply buttons, and display the appropriate data on PageOne? Here is my attempt:

import tkinter as tk
from functools import partial

characters = {"character1": "abc", "character2": "def", "character3": "ghi", "character4": "jkl", "character5": "mnp", "character6": "qrs" }

class AdventureGame:
    ''' controller for managiging frames '''
    def __init__(self, master):
        self.master = master
        self.frames = {}
        for F in (StartGame,ShowCharacters,CharacterDetail):
            frame = F(parent=master, controller=self)
            self.frames[F.__name__] = frame
            frame.grid(row=0, column=0, sticky="nsew")
        ''' rais the first frame '''
        self.raise_frame("StartGame")

    def raise_frame(self,page_name):
        ''' raise a frame '''
        frame = self.frames[page_name]
        frame.tkraise()

    def lower_frame(self,page_name):
        ''' lower a frame '''
        frame = self.frames[page_name]
        frame.lower()

class StartGame(tk.Frame):
  ''' introduction screen of the game '''
  def __init__(self, parent, controller):
    super(StartGame,self).__init__(parent)
    self.controller = controller
    ''' introduction text '''
    tk.Label(self, text="welcome to this game").grid()
    tk.Button(self, text="next", command=lambda: controller.raise_frame("ShowCharacters")).grid()

class ShowCharacters(tk.Frame):
  ''' main frame, overview of all pokemon '''
  def __init__(self, parent, controller):
    super(ShowCharacters,self).__init__(parent)
    self.controller = controller
    for row, character in enumerate(characters):
      name_label = tk.Label(self, text=characters[character])
      name_label.grid(row=row,column=0)
      info_button = tk.Button(self, text="view info", command=partial(self.switch,character))
      info_button.grid(row=row,column=1)

  def switch(self, character):
    test = self.controller.raise_frame("CharacterDetail")

class CharacterDetail(tk.Frame):
    ''' detail view of pokemon '''
    def __init__(self, parent, controller):
        super(CharacterDetail,self).__init__(parent)
        self.controller = controller
        tk.Button(self, text="back", command=lambda: controller.lower_frame("CharacterDetail")).grid()

     # somehow display characters name here
    def showdetail(self):
        tk.Label(self, text="test").grid()

def main():
    root = tk.Tk()
    app = AdventureGame(root)
    root.mainloop()
main()

It feels like the the key is in the controller, as explained here:

How to get variable data from a class

It just feels like i am missing something, does someone have an idea? Or am i thinking in the wrong direction all together?

If i try to show the detail:

def switch(self, character):
    test = self.controller.raise_frame("CharacterDetail")
    CharacterDetail.showdetail(self)

it shows up at the ShowCharacters frame rather then the CharacterDetail frame

I guess because self is the frame, which is self from ShowCharacters

I need to do something with the controller, but my mind just goes blank

So now i pass information to the controller:

import tkinter as tk
from functools import partial

characters = {"character1": "abc", "character2": "def", "character3": "ghi", "character4": "jkl", "character5": "mnp", "character6": "qrs" }

class AdventureGame:
    ''' controller for managiging frames '''
    def __init__(self, master):
        self.master = master
        self.frames = {}
        for F in (StartGame,ShowCharacters,CharacterDetail):
            frame = F(parent=master, controller=self)
            self.frames[F.__name__] = frame
            frame.grid(row=0, column=0, sticky="nsew")
        self.app_data = {"test": "test"}
        ''' rais the first frame '''
        self.raise_frame("StartGame")

    def raise_frame(self,page_name):
        ''' raise a frame '''
        frame = self.frames[page_name]
        frame.tkraise()

    def lower_frame(self,page_name):
        ''' lower a frame '''
        frame = self.frames[page_name]
        frame.lower()

class StartGame(tk.Frame):
  ''' introduction screen of the game '''
  def __init__(self, parent, controller):
    super(StartGame,self).__init__(parent)
    self.controller = controller
    ''' introduction text '''
    tk.Label(self, text="welcome to this game").grid()
    tk.Button(self, text="next", command=lambda: controller.raise_frame("ShowCharacters")).grid()

class ShowCharacters(tk.Frame):
  ''' main frame, overview of all pokemon '''
  def __init__(self, parent, controller):
    super(ShowCharacters,self).__init__(parent)
    self.controller = controller
    for row, character in enumerate(characters):
      name_label = tk.Label(self, text=characters[character])
      name_label.grid(row=row,column=0)
      info_button = tk.Button(self, text="view info", command=partial(self.switch,character))

      info_button.grid(row=row,column=1)

  def switch(self, character):
    test = self.controller.raise_frame("CharacterDetail")
    CharacterDetail.example(self)

class CharacterDetail(tk.Frame):
    ''' detail view of pokemon '''
    def __init__(self, parent, controller):
        super(CharacterDetail,self).__init__(parent)
        self.controller = controller
        tk.Button(self, text="back", command=lambda: controller.lower_frame("CharacterDetail")).grid()
    def example(self):
        tk.Label(self, text=self.controller.app_data["test"]).grid()


def main():
    root = tk.Tk()
    app = AdventureGame(root)
    root.mainloop()
main()

the label is still on the wrong frame, how can i get access to the right self so i can add the label to the right frame?

Community
  • 1
  • 1
stetim94
  • 64
  • 1
  • 11
  • What's the question? You made an attempt, what's the result of that attempt? Is it not working? What is it doing differently than you expect? – Bryan Oakley Dec 18 '16 at 15:01
  • # somehow display characters name here, i put this comment here. I somehow need to create a label which is added CharacterDetail frame. – stetim94 Dec 18 '16 at 16:02
  • i can't edit comments, that is bad. Anyway, i tried to add a method to CharacterDetail, but this wasn't working, i don't understand how i can access the frame – stetim94 Dec 18 '16 at 16:05

1 Answers1

1

As you call CharacterDetail.example(self) in function switch(...) of class ShowCharacters, self will be class ShowCharacters. Therefore the label created in function example(self) of class CharacterDetail will be in ShowCharacters frame.

Try:

  • return the raised frame in function raise_frame(...) of class AdventureGame:

    def raise_frame(self, page_name):
        frame = self.frames[page_name]
        frame.tkraise()
        return frame   # return the raised frame
    
  • modify function switch(...) of class ShowCharacters:

    def switch(self, character):
        frame = self.controller.raise_frame("CharacterDetail")
        frame.example()
    
acw1668
  • 40,144
  • 5
  • 22
  • 34
  • Awesome, thank you so much, exactly what i needed. Good explanation, makes perfect sense! Thanks to you i can move on, you made someone's day :) – stetim94 Dec 22 '16 at 09:33