Enable Dark Mode!
By: Ashok PK

Why Choose Tkinter for GUI Development in Python?

Python has gained immense popularity as a programming language, largely due to its simplicity and versatility. Tkinter emerges as a robust and beginner-friendly toolkit for those looking to build graphical user interfaces (GUIs) in Python. This comprehensive guide will explore Python GUI programming with Tkinter, examining its features, capabilities, and best practices. By the end, you will be equipped to create interactive and visually appealing applications with proficiency.

Why choose Tkinter for GUI development in Python?

Python provides numerous choices for crafting Graphical User Interfaces (GUIs). Among these methods, the tkinter stands out as the prevalent choice. Serving as a standard Python interface to the Tk GUI toolkit included with Python, tkinter offers the swiftest and most straightforward approach for constructing GUI applications. The process of crafting a GUI with Tkinter proves to be effortlessly manageable.

Installing Tkinter: Setup and requirements

* Make sure to install Python to your system before installing the Tkinter

* Install tkinter using the below command

sudo apt-get install python3-tk

* If you are using the customkinter install it using the command below.

python3 -m pip install customtkinter

Starting to create  Tkinter application

1. Importing required modules

import tkinter as tk
import customtkinter as ctk

Here, we import ‘tkinter’ and ‘customtkinter’.  We will develop the application using customtkinder, hence we import it accordingly.

2. Creating the main window of tkinter GUI application

class GUIApp(ctk.CTk):
   width = 950
   height = 650
   def __init__(self, *args, **kwargs):
      super().__init__(*args, **kwargs)
if __name__ == '__main__':
    app = GUIApp()

* The above code is to define a class named GUIApp that inherits from ctk.CTk. It seems that customtkinter  is a module or library being used in this code.

* The constructor method (__init__) for the GUIApp class. It is called automatically when an instance of the class is created.

* The *args and **kwargs are used to accept any number of positional and keyword arguments, respectively, to provide flexibility when initializing the class.

* super().__init__(*args, **kwargs) calls the constructor of the superclass (ctk.CTk). This ensures that any necessary initialization defined in the superclass is executed.

* The script checks if it is run directly, and if so, it creates an instance of the GUIApp class named app.

* app.mainloop() starts the main event loop of the GUI application, allowing it to respond to user inputs and events until the application is closed or terminated.

Layout management

Tkinter provides functionality for managing the layout and positioning of widgets within parent windows. This includes three primary geometry manager classes:

1. The `pack()` method: This arranges widgets in blocks before positioning them within the parent widget.

2. The `grid()` method: This organizes widgets in a grid or table-like structure before placing them within the parent widget.

3. The `place()` method: This enables the programmer to specify exact positions for widgets within the parent window.

class GUIApp(ctk.CTk):
        width = 950
        height = 650
        def __init__(self, *args, **kwargs):
            super().__init__(*args, **kwargs)
            # Create three labels to demonstrate different geometry managers
            label_pack = ctk.CTkLabel(self, text="Pack Example")
            label_grid = ctk.CTkLabel(self, text="Grid Example")
            label_place = ctk.CTkLabel(self, text="Place Example")
            # Using pack() method
            label_pack.pack(fill=tk.BOTH, expand=True)
            # Using grid() method
            label_grid.grid(row=0, column=1, padx=10, pady=10)
            # Using place() method
            label_place.place(x=100, y=100)
    if __name__ == '__main__':
        app = GUIApp()

* The pack() method is used to pack a widget.

* The grid() method is used to place a widget in the grid layout.

* The place() method is used to place  a widget at specific coordinates 

Exploring widgets in custom tkinter

1. CTkLabel:

It's one of the widgets in the custom tkinter and is used to display  some text in window.

label = ctk.CTkLabel(self, text="Its a sample text")

The main arguments are:


root, tkinter.Frame or CTkFrame

text variable

tkinter.StringVar object




label width in px


label height in px


corner radius in px


foreground color, tuple: (light_color, dark_color) or single color or "transparent"


label text color, tuple: (light_color, dark_color) or single color


label text font, tuple: (font_name, size)


controls where the text is positioned within a widget if the widget has more space than the text requires. The default value is "center", which centers the text within the available space.


control the postion of image relative to text, default is "center, other are: "top", "bottom", "left", "right"


determines the alignment of multiple lines of text within a widget, allowing you to align the text to the left, center it (the default), or align it to the right.


extra space added left and right of the text, default is 1


extra space added above and below the text, default is 1

2. CTkEntry

The CTkEntry widget in CustomTkinter provides a versatile tool for accepting text input from users within a graphical user interface (GUI) developed using Tkinter.

userName = ctk.CTkEntry(self, width=350,height=45,fg_color='white',text_color='#222222')
userPassword = ctk.CTkEntry(self, width=350, show='*', height=45,fg_color='white',text_color='#222222')




root, tkinter.Frame or CTkFrame


tkinter.StringVar object


entry width in px


entry height in px


corner radius in px


foreground color, tuple: (light_color, dark_color) or single color or "transparent"


entry text color, tuple: (light_color, dark_color) or single color


tuple: (light_color, dark_color) or single color


hint on the entry input (disappears when selected), default is None, don't works in combination with a textvariable


entry text font, tuple: (font_name, size)


"normal" (standard) or "disabled" (not clickable)

3. CTkCheckBox

A checkbox, also known as a tickbox or checkmark box, is a GUI element that allows users to select or deselect an option by clicking on a small square box. When the box is checked, it typically displays a checkmark or a tick symbol, indicating that the option is chosen. If unchecked, the box remains empty, indicating that the option is not selected.

def checkbox_event():
    print("checkbox toggled, current value:", check_var.get())
check_var = ctk.StringVar(value="on")
checkbox = ctk.CTkCheckBox(self, text="CTkCheckBox", command=checkbox_event, variable=check_var, onvalue="on", offvalue="off")

* prints a message indicating the toggled state of a checkbox along with its current value

* command=checkbox_event:  Specifies the function to be called when the checkbox is toggled.

* variable=check_var: Associates the checkbox with a Tkinter variable check_var.

* onvalue="on", offvalue="off": Defines the values to be assigned to the check_var when the checkbox is checked ("on") or unchecked ("off").

4. CTkOptionMenu

* The CTkOptionMenu serves as a drop-down menu that allows users to select from a list of predefined options.

* It is commonly used in graphical user interfaces (GUIs) to provide a compact way for users to choose from a set of values.

* The values argument holds a list of values that you want to display in the menu.

* When the user selects an option, you can associate a command function to execute.

Example code without the variable:

def optionmenu_callback(choice):
    print("Optionmenu dropdown clicked:", choice)
combobox = ctk.CTkOptionMenu(self, values=["option 1", "option 2"], command=optionmenu_callback)
combobox.pack(padx=20, pady=10)
combobox.set("option 2")  # Set initial value

With the variable :

optionmenu_var = ctk.StringVar(value="option 2")  # Set initial value
def optionmenu_callback(choice):
    print("Optionmenu dropdown clicked:", choice)
combobox = ctk.CTkOptionMenu(self, values=["option 1", "option 2"], command=optionmenu_callback, variable=optionmenu_var)
combobox.pack(padx=20, pady=10)




root, tkinter.Frame or CTkFrame


box width in px


box height in px


corner radius in px


foreground (inside) color, tuple: (light_color, dark_color) or single color


right button color, tuple: (light_color, dark_color) or single color


hover color, tuple: (light_color, dark_color) or single color


dropdown fg color, tuple: (light_color, dark_color) or single color


dropdown button hover color, tuple: (light_color, dark_color) or single color


dropdown text color, tuple: (light_color, dark_color) or single color


text color, tuple: (light_color, dark_color) or single color


text color when disabled, tuple: (light_color, dark_color) or single color


button text font, tuple: (font_name, size)


button text font, tuple: (font_name, size)


enable/disable hover effect: True, False


"normal" (standard) or "disabled" (not clickable, darker color)


function will be called when the dropdown is clicked manually


StringVar to control or get the current text


list of strings with values that appear in the option menu dropdown


enable/disable automatic resizing of optionmenu when text is too big to fit: True (standard), False


  "n", "s", "e", "w", "center", orientation of the text inside the optionmenu, default is "w"

5. CTkProgressBar

* The CTkProgressBar serves as a progress bar in your graphical user interfaces (GUIs).

* It allows you to visually represent the progress of a task or operation, such as file downloads, data processing, or any other time-consuming activity.

        self.title("Progress Bar")
        # Create a Progress Bar
        self.progress = CTkProgressBar(self)
        self.progress.pack(padx=20, pady=20)
        self.progress.set(0.25)  # Set initial progress value

* Before that we want to import the ProgressBar

from customtkinter import ctk, CTkProgressBar

* The initial progress value is set to 25% using set().

6. CTkRadioButton

* The CTkRadioButton works similarly to the standard tkinter.Radiobutton.

* It allows users to make one-of-many selections from a set of options.

* You can associate a Python function or method with each radio button. When a button is pressed, Tkinter automatically calls that function or method.

radio_var = ctk.IntVar(0)  # Initialize a variable to control the radio buttons
def radiobutton_event():
    print("Radiobutton toggled, current value:", radio_var.get())
radiobutton_1 = ctk.CTkRadioButton(self, text="CTkRadioButton 1", command=radiobutton_event, variable=radio_var, value=1)
radiobutton_2 = ctk.CTkRadioButton(self, text="CTkRadioButton 2", command=radiobutton_event, variable=radio_var, value=2)
radiobutton_1.pack(padx=20, pady=10)
radiobutton_2.pack(padx=20, pady=10)

* We create two CTkRadioButtons with different text labels.

* The command argument specifies the function to call when a button is clicked.

* The variable argument binds the radio buttons together, ensuring only one can be selected at a time.

7. CTkScrollbar

* The CTkScrollbar serves as a scroll bar within your graphical user interfaces (GUIs).

* It allows users to navigate through content that exceeds the visible area of a widget (such as a text box or canvas).

* You can use it to create scrollable text boxes, canvas views, or any other scrollable widgets.

        self.title("Scrollable Text Box")    
        # Create a TextBox and disable its default scrollbar
        self.textbox = CTkTextbox(self, activate_scrollbars=False)
        self.textbox.grid(row=0, column=0)      
        # Create a CTk scrollbar
        ctk_textbox_scrollbar = CTkScrollbar(self, command=self.textbox.yview)
        ctk_textbox_scrollbar.grid(row=0, column=1, sticky="ns")        
        # Connect the textbox scroll event to the CTk scrollbar      

8. CTkTextbox

* creates a versatile textbox widget 

* Scrollable: The textbox is scrollable both vertically and horizontally (with wrap='none').

* Insert, Get, and Delete Methods: It provides methods for inserting, retrieving, and deleting text based on indices.

        self.grid_rowconfigure(0, weight=1)
        self.grid_columnconfigure(0, weight=1)
        self.textbox = ctk.CTkTextbox(master=self, width=400, corner_radius=0)
        self.textbox.grid(row=0, column=0, sticky="nsew")
        self.textbox.insert("0.0", "Some example text!\n" * 50)
textbox = ctk.CTkTextbox(app)
textbox.insert("0.0", "new text to insert")  # insert at line 0 character 0
text = textbox.get("0.0", "end")  # get text from line 0 character 0 till the end
textbox.delete("0.0", "end")  # delete all text
textbox.configure(state="disabled")  # configure textbox to be read-only

9. CTkTabview

* The CTkTabview creates a tab view, similar to a notebook, within a tkinter application.

* Tabs are created using the .add("<tab-name>") method and are represented as CTkFrames.

* These tabs can be used just like regular CTkFrames, allowing you to place any widgets (buttons, labels, etc.) on them.

Code without using classes

import customtkinter
# Create a CTkTabview
tabview = customtkinter.CTkTabview(app)
tabview.pack(padx=20, pady=20)
# Add tabs
tabview.add("tab 1")  # Add a tab at the end
tabview.add("tab 2")  # Add another tab at the end
# Set the currently visible tab
tabview.set("tab 2")
# Example: Add a button to the first tab
button_1 = customtkinter.Button(tabview.tab("tab 1"))
button_1.pack(padx=20, pady=20)

It’s better to organize your code using classes. Here’s an example.

import customtkinter
class MyTabView(customtkinter.CTkTabview):
    def __init__(self, master, **kwargs):
        super().__init__(master, **kwargs)
        # Create tabs
        self.add("tab 1")
        self.add("tab 2")
        # Add widgets on tabs
        self.label = customtkinter.CTkLabel(master=self.tab("tab 1"))
        self.label.grid(row=0, column=0, padx=20, pady=10)
class App(customtkinter.CTk):
    def __init__(self):
        self.tab_view = MyTabView(master=self)
        self.tab_view.grid(row=0, column=0, padx=20, pady=20)
app = App()

Designing User Interfaces:

1. Working with fonts, colors, and images.

1. CTkImage

The CTkImage serves as a versatile vessel, accommodating a pair of PIL Image objects tailored for both light and dark modes. Accompanying this are dimensions denoted by a size tuple, dictating image width and height irrespective of scaling. Therefore, it is important to make sure that PIL Images have a higher resolution than the given size. This precaution guards against blurriness, particularly on high-definition 4K monitors employing 2x scaling. To uphold crispness on such displays, the provided PIL Images should boast resolutions twice that of the specified size.

from PIL import Image
my_image = customtkinter.CTkImage(light_image=Image.open("<path to light mode image>"),dark_image=Image.open("<path to dark mode image>"),size=(30, 30))
image_label = customtkinter.CTkLabel(app, image=my_image, text="")  # display image with a CTkLabel




PIL Image object for light mode


PIL Image object for dark mode


tuple (width in px, height in px) for rendering size independent of scaling

2. CTkFont

CustomTkinter offers two distinct approaches for font customization. Initially, one may opt for a tuple formation, typically structured as follows:

button = customtkinter.CTkButton(app, font=("<family name>", <size in px>, "<optional keywords>"))

However, it's worth noting that once established, this font configuration remains immutable. Optional attributes like normal/bold, roman/italic, underline, and overstrike can be appended to this tuple for further specification.

button = customtkinter.CTkButton(app, font=customtkinter.CTkFont(family="<family name>", size=<size in px>, <optional keyword arguments>))
button.cget("font").configure(size=new_size)  # configure font afterwards

Alternatively, a more flexible strategy involves the creation of a CTkFont object. Unlike the tuple method, this object allows subsequent modifications and can be employed across multiple widgets:

my_font = customtkinter.CTkFont(family="<family name>", size=<size in px>, <optional keyword arguments>)
button_1 = customtkinter.CTkButton(app, font=my_font)
button_2 = customtkinter.CTkButton(app, font=my_font)
my_font.configure(family="new name")  # changes apply to button_1 and button_2




The font family name as a string.


The font height as an integer in pixel.


'bold' for boldface, 'normal' for regular weight


'italic' for italic, 'roman' for unslanted.


True for underlined text, False for normal.


True for overstruck text, False for normal.

2. Styling and theming Tkinter applications

1. Color

 Each widget within CustomTkinter extends the flexibility of color customization, with detailed directives available in the corresponding widget documentation. It's essential to discern that while bg_color pertains solely to the backdrop color, visible only with rounded corners, the predominant hue defining a widget remains designated as fg_color:

Why Choose Tkinter for GUI Development in Python?-cybrosys

* Color customization in CustomTkinter offers versatility through three distinct formats: a single color name like "red", a hexadecimal color string such as "#FF0000", or a tuple comprising light and dark mode colors ("red", "darkred"). 

* Widgets intelligently select the appropriate color based on the current appearance mode. 

* Utilizing a tuple color scheme empowers widgets to exhibit varying hues in light and dark modes, while opting for a single color ensures consistent appearance across both modes.

button = customtkinter.CTkButton(root_tk, fg_color="red")  # single color name
button = customtkinter.CTkButton(root_tk, fg_color="#FF0000")  # single hex string
button = customtkinter.CTkButton(root_tk, fg_color=("#DB3E39", "#821D1A"))  # tuple color

2. Themes

In the realm of CustomTkinter, color schemes adhere to preset themes by default. Presently, three themes grace the palette: "blue", "dark-blue", and "green", with "blue" reigning as the default choice. Each theme offers tuple colors tailored for both light and dark appearance modes.

To initialize your preferred theme, simply incorporate the following code at the outset of your programming:

customtkinter.set_default_color_theme("dark-blue")  # Themes: "blue" (standard), "green", "dark-blue"

3. Custom Themes

Themes in CustomTkinter are delineated by .json files, exemplified by formats like dark-blue.json. Crafting bespoke themes is facilitated, eliminating the need for manual widget styling adjustments. 

Simply duplicate the aforementioned .json file and tweak the values to your preference. Subsequently, loading your custom theme entails passing the path to your .json file to the .set_default_color_theme method:


Advantages of custom tinkter widget:

1. Customization Opportunity:  Utilizing `CTkEntry` offers the chance for extensive customization, elevating both the visual appeal and functionality of entry widgets.

2. Improved User Engagement:  CustomTkinter empowers developers to fashion entry widgets with distinct styles, enriching the overall user experience.

3. Streamlined Data Management:  The entry widget streamlines the process of gathering user input, simplifying the integration of user-generated data into Python applications.

4. User-Friendly Interface:  CustomTkinter's `CTkEntry` seamlessly integrates with various GUI components, facilitating the creation of intricate interfaces with ease.

5. Community Assistance:  The CustomTkinter community offers valuable resources and assistance, supporting developers in effectively utilizing and addressing issues related to the `CTkEntry` widget.

 Python GUI programming with Tkinter offers limitless opportunities for developing intuitive and interactive applications. By mastering the basics and delving into advanced techniques, you can harness your creativity to build professional-grade GUIs effortlessly.

If you need any assistance in odoo, we are online, please chat with us.


Leave a comment




Cybrosys Technologies Pvt. Ltd.
Neospace, Kinfra Techno Park
Kakkancherry, Calicut
Kerala, India - 673635



Cybrosys Technologies Pvt. Ltd.
1st Floor, Thapasya Building,
Infopark, Kakkanad,
Kochi, India - 682030.



Cybrosys Techno Solutions
The Estate, 8th Floor,
Dickenson Road,
Bangalore, India - 560042

Send Us A Message