0

I am new OOP and UI development using tkinter. I currently have the following code:

class Snapshot_app(Tk):
    def __init__(self):
        Tk.__init__(self)
        container = Frame(self)
        container.pack(side="top", fill="both", expand=True)
        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()

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

        Label(self, text="Path to files").grid(row=1,column=0)

        self.fname = Entry(self)
        self.fname.grid(row=1, column=1)
        app.frames[PageTwo].dummy = self.fname.get()
        b = Button(self,text="Open Page 2",command=lambda:app.show_frame(PageTwo)).grid(row=2,column=1)

Class PageTwo(Frame):
    def __init__(self, parent, controller,dummy=None):
        Frame.__init__(self, parent)
        self.data = dummy     
        print(self.data)

app = Snapshot_app()
app.title("Snapshot Tool")
app.geometry("1200x400")
app.mainloop()

In PageTwo class, it gives me an error saying self.data=None. Which means I am unable to pass the dummy information from PageOne to PageTwo. However, if I put a button on PageTwo whose event triggers the printing of self.data, I am able to successfully get the data from PageOne. I would like to however really avoid usign the button. Any pointers and help would be much appreciated!

  • Have you researched all of the links in the following answer? https://stackoverflow.com/a/7557028/7432 – Bryan Oakley Nov 29 '18 at 17:52
  • @BryanOakley Thanks for the link. I have looked at this and in fact there are some other solutions that you and others have suggested elsewhere on stackoverflow that I tried as well. But fameman 's comment below is the exact problem I am trying to solve and I am not sure how to. – Random_User Nov 29 '18 at 18:30

1 Answers1

1

The problem is about the creation of the PageTwo instance. Your instantiate Snapshot_app(). The loop starts and instantiates StartPage, followed by PageOne. At this point PageOne.__init__ is being called which sets

app.frames[PageTwo].dummy = self.fname.get()

In my opinion, this shouldn't even work, because PageTwo was not added to app.frames yet, since the loop is till at the PageOne position. If this is the case, you should receive a KeyError: PageTwo. If this is not the case (I don't know, whether you shared the whole code) and if you already instantiated it somewhere else, then it would exist, but after the instantiation of PageOne, the for loop will proceed with PageTwo overriding the whole existing app.frames[PageTwo] entry and instantiating it without a dummy argument, therefore resulting in self.data = dummy being None.

fameman
  • 3,451
  • 1
  • 19
  • 31
  • I hope, I could point you in the right direction. Welcome to SO. – fameman Nov 29 '18 at 17:54
  • I think you are right. The PageTwo does get instatiated after the loop for PageOne completes which is where the app.frames[PageTwo].dummy gets initialized. But how do I get around this problem? Is there a better way to pass the variables from PageOne to PageTwo? – Random_User Nov 29 '18 at 18:20
  • Yes, if you are sure, PageTwo gets initialized after PageOne, you can write `self.data = app.frames[PageOne].fname.get()` instead of `self.data = dummy`. I even discovered another potential problem! You assign `app.frames[PageTwo].dummy` which **inside PageTwo** will be `self.dummy` whereas `dummy` will be the argument of the `__init__` class. I don't think that it works due to the reasons stated before, but **if it would**, you should use `self.data = self.dummy`. `dummy` is a local variable just usable **inside** the `__init__` function and therefore will always be `None`, since no... – fameman Nov 29 '18 at 19:03
  • ... parameters are provided. I hope I could help you and would like if you accept or upvote my answer if it worked. – fameman Nov 29 '18 at 19:03
  • I tried that and it now gives me an error: NameError: name 'app' is not defined – Random_User Nov 29 '18 at 19:21
  • I think that is because the snapshot_app is named app at the end of the script. I am guessing that as PageTwo gets initialized, it does not recognize the app but only knows of the Snapshot_app class defined earlier. – Random_User Nov 29 '18 at 19:22
  • Yes, I guess you are right. But, as you already pass the `self` of Snapshot_app's `__init__` as the `parent` argument to the indivual pages, you could just use `parent` instead off `app`. – fameman Nov 29 '18 at 21:11