Using your controller
Given that you already have the concept of a controller in place (even if you are not using it), you can use it to link between pages. The first step is to save the link to the controller on each page:
class PageOne(ttk.Frame): def __init__(self, parent, controller): self.controller = controller ... class PageTwo(ttk.Frame): def __init__(self, parent, controller): self.controller = controller ...
Then add a method to the controller, which will return the page when the class name or some other identifying attribute is specified. In your case, since your pages do not have an internal name, you can simply use the class name:
class MyApp(Tk): ... def get_page(self, classname): '''Returns an instance of a page given it class name as a string''' for page in self.frames.values(): if str(page.__class__.__name__) == classname: return page return None
Note: the above implementation is based on the code in question. The code in the question takes place in another answer here on stackoverflow. This code is slightly different from the source code in the way it manages pages in the controller. This uses the class reference as a key, the original answer uses the class name.
Using this function, any page can get a link to any other page by calling this function. Then, with a link to the page, you can access the public members of this page:
class PageTwo(ttk.Frame): ... def print_it(self): page_one = self.controller.get_page("PageOne") value = page_one.some_entry.get() print ('The value stored in StartPage some_entry = %s' % value)
Saving data in the controller
Direct access to one page from another is not the only solution. The disadvantage is that your pages are closely related. It would be difficult to make changes to one page without also making the corresponding changes to one or more other classes.
If your pages are designed to work together to define one data set, it may be wise to have this data stored in the controller so that any page does not need the internal design of other pages, Pages can freely implement widgets, but they donβt want to worry about what other pages can access these widgets.
You can have, for example, a dictionary (or database) in the controller, and each page is responsible for updating this dictionary with its subset of data. Then at any time you can simply request a controller for the data. In fact, the page signs the contract, promising to keep its subset of global data up to date with what is in the graphical interface. As long as you maintain the contract, you can do whatever you want when implementing the page.
To do this, the controller will create a data structure before creating the pages. Since we use tkinter, this data structure can consist of instances of StringVar or any other Var class. This is not necessary, but it is convenient and easy in this simple example:
class MyApp(Tk): def __init__(self): ... self.app_data = {"name": StringVar(), "address": StringVar(), ... }
Then you modify each page to refer to the controller when creating widgets:
class PageOne(ttk.Frame): def __init__(self, parent, controller): self.controller=controller ... self.some_entry = ttk.Entry(self, textvariable=self.controller.app_data["name"], ...)
Finally, you then access the data from the controller, not from the page. You can throw away get_page and print this value as follows:
def print_it(self): value = self.controller.app_data["address"].get() ...