-1

I have code below originally taken from the link here i have read all documentation in there but i feel im overlooking something, i have pages in separate modules as well as a separate module with a Add class for adding pages to the window.

The idea is to later be able to drop a module in a sub folder with a Pagexxx object within it and call the add page class to allow Tkinter to display it but i cannot seem to get the frames to stack.

Nav.py

import tkinter as tk
from Page import PageList
import Mypages

class Windowhandler(tk.Tk):

    def __init__(self, *args, **kwargs):
        tk.Tk.__init__(self, *args, **kwargs)
        container = tk.Frame(self)
        container.pack(side="top", fill="both", expand= True)
        container.grid_rowconfigure(0, weight=1)
        container.grid_columnconfigure(0, weight=1)

        PageList("Page1", container, self, Mypages.PageOne)
        PageList("Page2", container, self, Mypages.PageTwo)
        self.show_frame("Page1")

    def show_frame(self, cont):
        frameref = PageList.frames[cont]
        print(frameref)
        frameref.tkraise()



app = Windowhandler()
app.mainloop()

Page.py

class PageList():
frames = {}
def __init__(self, name, parent, cont, ref):
    self.frames[name] = ref(parent=parent, controller=cont)

Mypages.py

import tkinter as tk

class PageOne(tk.Frame):
    def __init__(self, parent, controller):
        this = tk.Frame.__init__(self, parent)
        label = tk.Label(this, text="Welcome to Page 1")
        label.pack(pady=10, padx=10)

        button1 = tk.Button(this, text="Back to Home",
                    command=lambda: controller.show_frame("Page2"))
        button1.pack()

class PageTwo(tk.Frame):
    def __init__(self, parent, controller):
        this = tk.Frame.__init__(self, parent)
        label = tk.Label(this, text="Welcome to Page 2")
        label.pack(pady=10, padx=10)

        button1 = tk.Button(this, text="Back to Home",
                    command=lambda: controller.show_frame("Page1"))
        button1.pack()

Example

Chris James
  • 151
  • 2
  • 14
  • As it stands, your class definition in `Page.py` is wrong: Take the tour [Python - Object Oriented](https://www.tutorialspoint.com/python/python_classes_objects.htm) – stovfl Dec 27 '19 at 17:24
  • Thank you for your input. i believe i have rectified this in my edit. – Chris James Dec 27 '19 at 17:53

1 Answers1

1

Before asking for help from others, the first step is to validate your assumptions. You're assuming that tk.Frame.__init__(self, parent) returns something useful, but you never validated that assumption by checking to see if it is what you think it is.

The first problem is illustrated by two lines, which are essentially the same in both pages:

this = tk.Frame.__init__(self, parent)
label = tk.Label(this, text="Welcome to Page 1")

I'm guessing you were assuming that this would be set to the instance of the Frame. However, the __init__ function returns None so this is set to None. When None is passed as the parent of a widget, that widget becomes a child of the root window.

The solution is to not use this. Use self:

tk.Frame.__init__(self, parent)
label = tk.Label(self, text="Welcome to Page 2")

The second problem is that you never add the page to the container with grid, pack, or place, so they will never be visible.

You need to change Add to actually add the page to the container:

def Add(name, parent, cont, ref):
    PageList.frames[name] = ref(parent=parent, controller=cont)
    PageList.frames[name].grid(row=0, column=0, sticky="nsew")
Bryan Oakley
  • 370,779
  • 53
  • 539
  • 685
  • Thank you so much @Bryan Oakley that made sense, if you may of guessed i am still relatively new to python but appreciate your tip on verifying my assumption i did as you said and checked, as for forgetting to add it to the container i must of become code blind over the last few hours having checked the code in the link above its clearly there. – Chris James Dec 27 '19 at 18:08