Search code examples
pythonclasstkinterargumentsparameter-passing

Python Tkinter - Passing controllers as arguments of a tkinter frame


I've got a main class called App that invokes 4 controllers. The method start_from_home_page() creates an object of type HomePage and I want this object to have access to all 4 controllers which I will pass as arguments. Here's the method:

    def start_from_home_page(self, fileSystemController, widgetController, logicController):
        from pages.HomePage import HomePage
        self.homePage = HomePage(self, fileSystemController, widgetController, logicController)
        self.homePage.grid(row = 0, column = 0, sticky = 'nsew')
        self.homePage.tkraise()

And here's the 'App' class

class App(ctk.CTk):
    def __init__(self, title, dim):

        # main setup
        super().__init__()
        self.title(title)
        self.geometry(f'{dim[0]}x{dim[1]}')
        self.minsize(dim[0],dim[1])
        

        os.chdir('/Users/mauri5566/Desktop/AST-CVE')

        self.widgetController = WidgetController(self)
        self.fileSystemController = FileSystemController(self)
        self.logicController = LogicController(self)
        self.navigationController = NavigationController(self)

        self.navigationController.start_from_home_page(self.fileSystemController, self.widgetController, self.logicController)

        self.mainloop()

App('AST-CVE', (1000,800))

The following code shows the initial part of the HomePage class (which inherits from ctk.CTkFrame). I'm getting the following error:

bad screen distance ".!filesystemcontroller"

That's because the third argument is supposed to be the width of the frame. However I don't need that, I just want the class to have access to the controllers by passing them as arguments, how can I do that?

Here's the HomePage class:

class HomePage(ctk.CTkFrame):
    def __init__(self,  navigationController: NavigationController,
                        fileSystemController: FileSystemController,
                        widgetController: WidgetController,
                        logicController: LogicController):
        super().__init__(navigationController, fileSystemController, widgetController, logicController)

Just for clarity, this is how a ctk.CTkFrame object is structured:

class CTkFrame(CTkBaseClass):
    
    def __init__(self,
                 master: Any,
                 width: int = 200,
                 height: int = 200,
                 corner_radius: Optional[Union[int, str]] = None,
                 border_width: Optional[Union[int, str]] = None,

                 bg_color: Union[str, Tuple[str, str]] = "transparent",
                 fg_color: Optional[Union[str, Tuple[str, str]]] = None,
                 border_color: Optional[Union[str, Tuple[str, str]]] = None,

                 background_corner_colors: Union[Tuple[Union[str, Tuple[str, str]]], None] = None,
                 overwrite_preferred_drawing_method: Union[str, None] = None,
                 **kwargs):


Solution

  • You should not be passing those arguments to super.__init__. There's no need to since the superclass knows nothing about them.

    You just need to save references to them inside of your custom __init__:

    class HomePage(ctk.CTkFrame):
        def __init__(self,  navigationController: NavigationController,
                            fileSystemController: FileSystemController,
                            widgetController: WidgetController,
                            logicController: LogicController):
            super().__init__()
            self.navigationController = navigationController
            self.fileSystemController = fileSystemController
            self.widgetController = widgetController
            self.logicController = logicController
    

    However, since your instance of app has references to all of these instances, you can just pass the instance of app and then reference them through that.