1

I am currently working on a project using the customtkinter library. The complexity of the project has grown to a point where I'm having trouble locating the widgets. To address this, I plan to organize the widgets by importing them from a dedicated "widgets" folder. This way, I can use statements like "from widgets import button, entry" to manage them more effectively.

Here is main.py file

import customtkinter as ctk

class App(ctk.CTk):
    def __init__(self):
        super().__init__()
        self.length = 13

        self.title("my app")
        self.geometry("505x585")
        ctk.set_appearance_mode("Dark")
        

if __name__ == "__main__":
    app = App()
    app.mainloop()

I tried to make this but it's working.

import customtkinter as ctk
from widgets.button import Button

class App(ctk.CTk):
    def __init__(self):
        super().__init__()
        self.length = 13

        self.title("my app")
        self.geometry("505x585")
        ctk.set_appearance_mode("Dark")
        
        
        # Button Widget
        self.btn = Button(master=self, text='Hi')
        self.btn.place(relx=0.5, rely=0.5)
    

if __name__ == "__main__":
    app = App()
    app.mainloop()

Here is my button.py file placed in widgets folder.

from customtkinter import CTkButton


class Button:
    def __init__(self):
        self.button = CTkButton(
            text="Hmm",
        )

Furthermore, my aim is to assign default values to each widget. In cases where I don't provide specific arguments within the main file for the widget instances, these widgets will seamlessly adopt the predefined default values.

Py Linux
  • 21
  • 4

2 Answers2

2

Button class should inherit from CTkButton instead of creating instance of CTkButton internally, otherwise self.btn inside App is not a widget itself and so .place(...) cannot be called on it. Also you need to pass those keyword arguments to the Button.__init__():

from customtkinter import CTkButton

class Button(CTkButton):
    def __init__(self, master=None, **kwargs):
        # if option "text" not provided, set it to "Hmm"
        text = kwargs.pop("text", "Hmm")
        super().__init__(master, text=text, **kwargs)
acw1668
  • 40,144
  • 5
  • 22
  • 34
0

Answer Of 1st Question

The reason you're encountering an issue with the Button instance not working is due to passing keyword arguments without receiving them in the button.py file. To resolve this, use **kwargs in the Button class constructor.

Here are the necessary changes you need to make:

class Button:
    def __init__(self, **kwargs):

        // code...

Since you're providing two keyword arguments, namely "master" and "text" in the main.py file, here is how you can handle them in the button.py file.

class Button:
    def __init__(self, **kwargs):
        self.button = CTkButton(
            master=kwargs['master'],
            text=kwargs['text']    
        )

Answer Of 2nd Question

For the second question, the solution is to utilize the dictionary's get method. This method returns the value for a given key if the key is present in the dictionary; otherwise, it returns a default value.

Here's how you can achieve this:

from customtkinter import CTkButton

class Button:
    def __init__(self, **kwargs):
        self.button = CTkButton(
            master=kwargs.get('master', self),
            text=kwargs.get('text', 'Button')    
        )

If you don't pass the "text" argument from the main.py file, the button.py file will automatically use the default value.

Elie Hacen
  • 372
  • 12