Home > Software design >  Changing the state of root Tk from another class/file in tkinter
Changing the state of root Tk from another class/file in tkinter

Time:12-12

I am creating a tkinter app and I have come across a problem that I can't solve. I have seperated each page into its own file, to make it easier in the long run as the program grows substantially. One Page that I want to call/show requires the window to be maximised, but otherwise I want to window to be 400x400. I cannot find a way to change the state of root = Tk() from another file. I have provided a MVP below.

# main.py

from window import Window

myWindow = Window()
myWindow.start()
window.py

from tkinter import *
from mainView import MainView


class Window:
    def __init__(self):
        self.root = Tk()
        self.root.title("Tkinter Window")
        self.root.geometry("400x400")

        self.startView = MainView(self.root)
        self.startView.pack(side=TOP, fill=BOTH, expand=True)

    def start(self):
        self.root.mainloop()
# mainView.py

from tkinter import *
from homePage import HomePage
from firstPage import FirstPage


class MainView(Frame):
    def __init__(self, *args, **kwargs):
        Frame.__init__(self, *args, **kwargs)
        self.mainFrame = Frame
        container = Frame(self)
        container.pack(side=TOP, fill=BOTH, expand=True)

        container.grid_rowconfigure(0, weight=1)
        container.grid_columnconfigure(0, weight=1)

        self.frames = {}

        for F in (HomePage, FirstPage):
            frame = F(container, self)

            self.frames[F] = frame

            frame.grid(row=0, column=0, sticky=NSEW)

        self.show_frame(HomePage)
        
    def show_frame(self, cont):
        frame = self.frames[cont]
        frame.tkraise()
# homePage.py

from tkinter import *
from page import Page
from firstPage import FirstPage


class HomePage(Page):
    def __init__(self, parent, controller):
        Page.__init__(self, parent)

        container = Frame(self)
        container.pack(side=TOP,
                       fill=BOTH,
                       expand=True,
                       padx=8,
                       pady=8)

        welcome = Label(container,
                        text="Welcome to Earl")
        welcome.pack(side=TOP,
                     fill=BOTH,
                     expand=True,
                     padx=8,
                     pady=8)

        container_buttons = Frame(container)
        container_buttons.pack(side=TOP,
                               fill=BOTH,
                               expand=True,
                               padx=8,
                               pady=8)

        container_buttons.columnconfigure(0,
                                          weight=1)
        container_buttons.columnconfigure(1,
                                          weight=1)

        for i, page in enumerate((FirstPage), 0):
            if i % 2 != 0:
                container_buttons.rowconfigure(int((i - 1) / 2),
                                               weight=1)
                Button(container_buttons,
                       text=page.name,
                       command=lambda p=page: controller.show_frame(p)).grid(column=1,
                                                                             row=int((i - 2) / 2),
                                                                             sticky=NSEW,
                                                                             padx=8,
                                                                             pady=8)
            else:
                Button(container_buttons,
                       text=page.name,
                       command=lambda p=page: controller.show_frame(p)).grid(column=0,
                                                                             row=int((i - 1) / 2),
                                                                             sticky=NSEW,
                                                                             padx=8,
                                                                             pady=8)
# firstPage.py

from tkinter import *
import homePage
from page import Page


class FirstPage(Page):
    name = "First Page"

    def __init__(self, parent, controller):
        Page.__init__(self, parent)

        container = Frame(self)
        container.pack(side=TOP,
                       fill=BOTH,
                       expand=True,
                       padx=8,
                       pady=8)

        container.columnconfigure(0, weight=1)
        container.columnconfigure(1, weight=1)

        label_title = Label(container,
                            text="First Page")
        label_title.grid(row=0,
                         column=0,
                         columnspan=2,
                         sticky=NSEW)

        self.entries = {}

        for i, name in enumerate(("Name",
                                  "Number of Columns",
                                  "Number of Rows"),
                                 1):
            container.rowconfigure(i, weight=1)

            label = Label(container,
                          text=name)
            label.grid(row=i,
                       column=0,
                       sticky=EW,
                       padx=8,
                       pady=8)

            entry = Entry(container)
            self.entries[name] = entry
            entry.grid(row=i,
                       column=1,
                       sticky=EW,
                       padx=8,
                       pady=8)

        button_back = Button(container,
                             text="Back",
                             command=lambda c=controller: c.show_frame(homePage.HomePage))
        button_back.grid(row=4,
                         column=0,
                         sticky=NSEW,
                         padx=8,
                         pady=8)

What I want is when you press the "First Page" button on the Home Page I want to maximise the window. I have tried creating a changeState function in all of the 5 files above, but ive had no luck.

My thinking was that I would have to do it through main.py as that is the initialisation of the root window, but I get a ImportError: cannot import name 'Window' from partially initialized module 'window' error.

Any help/pointing me in the right direction would be greatly appreciated, if you need more info I will update this question with the needed info.

CodePudding user response:

You can get the root window for any widget with the winfo_toplevel command. So, you should be able to use self.winfo_toplevel inside any of your classes.

Or, since you have a controller, put a function in the controller and then call the function via the controller.

  • Related