Skip to content

App structure and layout

Tom Schimansky edited this page Jul 17, 2022 · 2 revisions

Recommendations

Unless your program is just a test, you should always structure you're app into classes which inherit from customtkinter.CTk for the main window and customtinter.CTkToplevel or customtkinter.CTkFrame for toplevel windows or frames. By doing so you will get clear and readable code and an expandable app.

⚠️⚠️⚠️ Writing a lot of UI code without classes and in single .py file with global variables like it's often done is a pain to read and very bad coding style!

The second recommendation is to never use the .place() geometry manager, but to use .pack() for very small apps or .grid() in every other case. The problem with .place() is that it seems simple at the beginning, when you just place a few widgets on a window. But you block yourself from extending your app. If you want to insert a widget at the top, you have to correct the positions of every other widgets below. With grid or pack all the widgets move and align automatically with a given padding and min/max size. By using place you will never get a consistent padding and a responsive window.

Minimal onefile example app with .pack()

import customtkinter


class App(customtkinter.CTk):
    def __init__(self):
        super().__init__()

        self.title("minimal example app")
        self.minsize(400, 300)

        self.button = customtkinter.CTkButton(master=self, command=self.button_callback)
        self.button.pack(padx=20, pady=20)

    def button_callback(self):
        print("button pressed")


if __name__ == "__main__":
    app = App()
    app.mainloop()
Bildschirmfoto 2022-07-17 um 17 17 00

Small onefile example app with .grid()

Now we use the grid geometry manager to create a 2x2 grid system. The first row gets a weight of 1 so it will expand. The second row has a default weight of 0 and will only be as big as it needs to be to fit the widgets inside of it. Both columns get an equal weight of 1 so that they expand equally and fill the window.

The textbook has a column span of 2 so it will fill the first row completely. By setting sticky to nsew, we force the textbook to stick to all edges of the grid cells it is in. It will expand and completely fill the first row. So set the x-padding to 20 on both sides and the y-padding to (20, 0) so that there is no padding at the bottom. (It will come from the buttons and the entry in the second row)

The entry and button get a padding of 20 on all sides and a sticky of ew, so that they will expand horizontally and fill the whole grid cell they are in.

import customtkinter


class App(customtkinter.CTk):
    def __init__(self):
        super().__init__()

        self.geometry("500x300")
        self.title("small example app")
        self.minsize(300, 200)

        # create 2x2 grid system
        self.grid_rowconfigure(0, weight=1)
        self.grid_columnconfigure((0, 1), weight=1)

        self.textbox = customtkinter.CTkTextbox(master=self)
        self.textbox.grid(row=0, column=0, columnspan=2, padx=20, pady=(20, 0), sticky="nsew")

        self.combobox = customtkinter.CTkComboBox(master=self, values=["Sample text 1", "Text 2"])
        self.combobox.grid(row=1, column=0, padx=20, pady=20, sticky="ew")
        self.button = customtkinter.CTkButton(master=self, command=self.button_callback, text="Insert Text")
        self.button.grid(row=1, column=1, padx=20, pady=20, sticky="ew")

    def button_callback(self):
        self.textbox.insert("insert", self.combobox.get() + "\n")


if __name__ == "__main__":
    app = App()
    app.mainloop()
Bildschirmfoto 2022-07-17 um 17 33 55

⚠️ Attention ⚠️

The Github Wiki is outdated, the new documentation can be found at:

https://customtkinter.tomschimansky.com

Clone this wiki locally