Library / SDK
TomSchimansky/CustomTkinter avatar
TomSchimansky/CustomTkinter

CustomTkinter: Modern Dark-Mode Python GUI on Top of Tkinter

A modern and customizable python UI-library based on Tkinter

13,570 stars1,163 forksPythonMIT

At a glance

What is it?
CustomTkinter is a Python UI library built on Tkinter that replaces the default widgets with modern, fully customizable counterparts. It responds to the system's light or dark mode setting, scales correctly on high-DPI displays on Windows and macOS, and works alongside standard Tkinter elements so existing Tkinter code does not need a full rewrite.
Who is it for?
CustomTkinter is worth adopting for Python desktop applications where appearance matters and the team wants to stay in the Tkinter ecosystem without switching to a heavier framework. It is not the right tool for projects that need native platform controls, complex layout engines, or advanced graphics: Tkinter's underlying limitations still apply.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 97 days ago.
What is it written in?
Mainly Python, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 27, 2026, and from our analysis. They are not legal advice.

Editorial analysis

What CustomTkinter Adds Over Standard Tkinter

Standard Tkinter produces visually dated interfaces. Buttons, entry fields, and frames use the operating system's default rendering from several years ago, and there is no built-in dark mode support. CustomTkinter solves this by providing drop-in replacement widgets that look modern, respect the system appearance mode, and scale with the display's DPI setting.

The README states that CustomTkinter widgets can be used in combination with normal Tkinter elements. This means existing Tkinter applications can adopt CustomTkinter incrementally: replace individual widgets where appearance matters and leave the rest in place. The appearance mode (system, light, or dark) and the color theme (blue, dark-blue, or green) are set at the application level through two function calls before the main loop starts.

HighDPI scaling support applies to Windows and macOS. On Linux, the README does not claim HighDPI support. The library currently stands at version 6.0.0 as listed in `pyproject.toml`.

Installation and a First Window

Install the package with pip:

code
pip3 install customtkinter

To update an existing installation:

code
pip3 install customtkinter --upgrade

A minimal example from the README creates a window with a single button:

python
import customtkinter

customtkinter.set_appearance_mode("System")
customtkinter.set_default_color_theme("blue")

app = customtkinter.CTk()
app.geometry("400x240")

def button_function():
    print("button pressed")

button = customtkinter.CTkButton(master=app, text="CTkButton", command=button_function)
button.place(relx=0.5, rely=0.5, anchor=customtkinter.CENTER)

app.mainloop()

The `CTk` class replaces the standard `Tk` root window. Widget names follow the pattern `CTk` plus the widget type (CTkButton, CTkEntry, CTkFrame, and so on). To see all available widgets at once, run the showroom:

python
import customtkinter as ctk
ctk.run_showroom()

Appearance Modes, Themes, and the Widget Set

CustomTkinter provides three appearance modes: `System` (follows the OS setting), `Light`, and `Dark`. The mode is set with `customtkinter.set_appearance_mode()` before creating the main window. On Windows 10 and 11, the library responds to system-level dark/light mode switches at runtime, and the README includes video demonstrations of this behavior.

On macOS, a dark window title bar requires Python 3.10 or higher, or the Anaconda Python distribution (Tcl/Tk 8.6.9 or later), according to the README.

Three color themes are available: `blue` (the default), `dark-blue`, and `green`. Themes are set with `set_default_color_theme()`. Custom themes are not documented in the README.

The widget set includes buttons with image support, scrollable frames in both vertical and horizontal orientation, and support for third-party Tkinter widgets such as TkinterMapView (a tile-based map widget). The README demonstrates a map example integrating OpenStreetMap tiles.

Dependency Structure and Platform Notes

CustomTkinter's direct dependencies are minimal. The `requirements.txt` lists `darkdetect~=0.7.0` for detecting the system appearance mode, `typing-extensions~=4.4.0`, `packaging`, and `setuptools`. There are no compiled extensions or platform-native bindings beyond what Tkinter itself provides.

The library runs on Windows, macOS, and Linux. The README's cross-platform statement covers consistent appearance across those three platforms. The degree of visual consistency depends on the underlying Tkinter version and the system's fonts; the README does not describe known platform-specific rendering differences.

For Windows, WebView2 or any browser component is not involved. CustomTkinter is a pure Tkinter-based library. It does not embed a web renderer.

The repository includes a pre-commit configuration file for development, a CHANGELOG.md documenting the history of changes, and an examples folder. The examples folder contains complex_example.py, which the README uses to demonstrate dark mode switching and appearance mode changes in video recordings, image_example.py for buttons with images, and scrollable_frame_example.py.

The widget naming convention prefixes standard Tkinter widget names with CTk. The root window class is CTk instead of Tk. The library follows the same constructor interface as standard Tkinter: widgets take a master argument and support placement with pack, grid, and place. The CTkButton class accepts an image argument and a compound argument for controlling the relative position of text and image. Scrollable frames work in both vertical and horizontal orientations and can be nested with other widgets. The run_showroom() function starts an application that displays all available widgets at once, which is the fastest way to see the full widget set without reading the documentation.

Where CustomTkinter Falls Short

Tkinter's layout engine, event model, and performance characteristics still apply. Tkinter does not support GPU-accelerated rendering, complex animation, or hardware-accelerated 2D drawing. Applications that need those capabilities, such as data visualization tools with large interactive charts, are better served by a different toolkit.

The widget count in CustomTkinter is smaller than in PyQt6 or wxPython. Complex UI patterns that require tree views, dockable panels, MDI windows, or rich text editors will require either finding third-party Tkinter widgets or switching frameworks.

The README encourages frequent updates ("update as often as possible because this library is under active development"), but the repository has no GitHub releases and version 6.0.0 has been the current version since the reference material was collected. The last push to the master branch was on 2026-06-24.

CustomTkinter Compared to PyQt6

PyQt6 is the primary alternative for developers who outgrow Tkinter. PyQt6 wraps the Qt framework, which provides native-looking controls on all three major platforms, a richer widget set, a signal-slot event model, and Qt Designer for visual layout editing.

The trade-off is size and licensing. PyQt6 requires the GPL or a commercial licence, which matters for proprietary applications. CustomTkinter is MIT-licensed, with no restriction on commercial use. PyQt6 introduces a larger dependency footprint and a steeper learning curve for developers already familiar with Tkinter.

For small to medium desktop utilities where visual appearance and dark mode matter but the widget requirements are simple, CustomTkinter provides a lower-friction path. For large applications with complex UI requirements, the investment in PyQt6 is usually justified.

On Windows specifically, CustomTkinter handles HighDPI scaling and dark title bars through built-in mechanisms that do not require any manual DPI awareness calls or theming code. The library defaults to the "blue" color theme and "System" appearance mode, which means applications inherit the correct light or dark setting automatically without any configuration from the developer.

Editorial conclusion

CustomTkinter is worth adopting for Python desktop applications where appearance matters and the team wants to stay in the Tkinter ecosystem without switching to a heavier framework. It is not the right tool for projects that need native platform controls, complex layout engines, or advanced graphics: Tkinter's underlying limitations still apply. Before starting a new project, check the version history in CHANGELOG.md and confirm that the widget set in version 6.0.0 covers the UI components needed, since CustomTkinter's widget selection is smaller than PyQt6's.

Frequently asked questions

Is CustomTkinter better than Tkinter?

CustomTkinter adds modern widget appearance, dark mode support, and HighDPI scaling that standard Tkinter lacks. It is built on Tkinter and uses the same programming model, so it is not a replacement for the underlying framework but a visual upgrade layer over it.

What is CustomTkinter?

CustomTkinter is a Python UI library based on Tkinter that provides modern, fully customizable widgets with dark/light mode support and HighDPI scaling. Widgets are created the same way as standard Tkinter widgets and can be mixed with them.

How do I install CustomTkinter?

Run `pip3 install customtkinter` to install, or `pip3 install customtkinter --upgrade` to update an existing installation. No additional build tools or compiled dependencies are required beyond Tkinter itself.

Official sources

  1. Issues
  2. License: MIT
  3. README
  4. TomSchimansky/CustomTkinter on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/tomschimansky-customtkinter.svg)](https://hysenlabs.com/projects/tomschimansky-customtkinter)