Themed Tkinter Text widget with modern styling support.
- 🎨 Theme-aware text widget that automatically adapts to ttk themes
- 📜 Built-in ScrolledText component with vertical/horizontal scrollbars
- 🖥️ Native integration with ttk styles and themes
- 🔄 Dynamic theme switching support
Example screenshots of Windows 11, Windows 10, and Windows 7.
You can install ttk-text using your preferred package manager.
Since ttk-text is currently unstable, I strongly recommend installing it in a virtual environment and pinning the exact version to avoid compatibility issues.
# Using pip
pip install ttk-text
# Using uv
uv add ttk-text
# Using PDM
pdm add ttk-text
# Using Poetry
poetry add ttk-textttk-text provides three widgets:
ttk_text.ThemedTextFrame: A Frame for rendering the textbox style, which will bind to a Text widget.ttk_text.ThemedText: A themed Text widget, as a replacement fortkinter.Text.ttk_text.scrolled_text.ScrolledText: An extension ofThemedTextwith vertical/horizontal scrollbars, as a replacement fortkinter.scrolledtext.ScrolledText.
You can use ThemedText and ScrolledText just like you would use tkinter.Text.
Here's an example:
from tkinter import Tk
from ttk_text import ThemedText
from ttk_text.scrolled_text import ScrolledText
root = Tk()
themed_text = ThemedText(root)
themed_text.pack(fill="both", expand=True, padx="7p", pady="7p")
scrolled_text = ScrolledText(root)
scrolled_text.pack(fill="both", expand=True, padx="7p", pady=(0, "7p"))
root.mainloop()Note
Currently, ttk style properties will override attributes you set such as selectbackground.
ThemedText itself doesn't handle theming; instead, it wraps itself in a ThemedTextFrame and lets the ThemedTextFrame handle theming. You can access this ThemedTextFrame via ThemedText#frame.
ThemedText positions itself at grid position (1, 1) within ThemedText#frame.
Layout of ThemedText#frame:
| Index | 0 | 1 | 2 |
|---|---|---|---|
| 0 | |||
| 1 | ThemedText |
||
| 2 |
ScrolledText also adds scrollbars and a frame for corner junction aesthetics.
Layout of ScrolledText#frame:
| Index | 0 | 1 | 2 |
|---|---|---|---|
| 0 | |||
| 1 | ThemedText |
Scrollbar(orient="vertical") |
|
| 2 | Scrollbar(orient="horizontal") |
Frame |
You can place other components around (1, 1) like with ScrolledText, and call ThemedText#frame.bind_widget() to bind the component.
You can use ThemedTextFrame to theme third-party Text components.
After adding the component, you need to call ThemedText#frame.bind_text() to bind the third-party Text component.
For example, using tkinter.scrolledtext.ScrolledText:
import tkinter.scrolledtext
from tkinter import Tk
from ttk_text import ThemedTextFrame
root = Tk()
text_frame = ThemedTextFrame(root)
text_frame.pack(fill="both", expand=True, padx="7p", pady="7p")
text_frame.grid_rowconfigure(1, weight=1)
text_frame.grid_columnconfigure(1, weight=1)
text = tkinter.scrolledtext.ScrolledText(text_frame)
text.grid(row=1, column=1, sticky="nsew")
text_frame.bind_text(text)
root.mainloop()Note
ThemedTextFrame internally requires grid layout, you cannot use pack or place layouts.
You can use style name ThemedText.TEntry to configure styling.
| Property | Description |
|---|---|
borderwidth |
ThemedTextFrame border width |
padding |
ThemedTextFrame internal padding |
fieldbackground |
Text background color |
foreground |
Text font color |
textpadding |
Text external padding |
insertwidth |
Text cursor width |
selectbackground |
Text selection background color |
selectforeground |
Text selection font color |
For example, to set the border width to 1.5p:
from tkinter.ttk import Style
style = Style()
style.configure("ThemedText.TEntry", borderwidth="1.5p")Some third-party themes may not be fully compatible with ttk-text. You can call the following function after setting the theme:
Sun Valley ttk theme
from tkinter import Tk
from tkinter.ttk import Style
import sv_ttk
def fix_sv_ttk(style: Style):
if sv_ttk.get_theme() == "light":
style.configure("ThemedText.TEntry", fieldbackground="#fdfdfd", textpadding=5)
style.map(
"ThemedText.TEntry",
fieldbackground=[
("hover", "!focus", "#f9f9f9"),
],
)
else:
style.configure("ThemedText.TEntry", fieldbackground="#292929", textpadding=5)
style.map(
"ThemedText.TEntry",
fieldbackground=[
("hover", "!focus", "#2f2f2f"),
("focus", "#1c1c1c"),
],
)
# Example
app = Tk()
sv_ttk.set_theme("light")
fix_sv_ttk(Style())
app.mainloop()Azure-ttk-theme
from tkinter import Tk
from tkinter.ttk import Style
def fix_azure_ttk(style: Style):
if style.theme_use() == "azure-light":
style.configure("ThemedText.TEntry", fieldbackground="#ffffff", textpadding=5)
else:
style.configure("ThemedText.TEntry", fieldbackground="#333333", textpadding=5)
# Example
app = Tk()
app.tk.call("source", "azure.tcl")
Style().theme_use("azure-light")
app.tk.call("set_theme", "light")
fix_azure_ttk(Style())
app.mainloop()Forest-ttk-theme
from tkinter import Tk
from tkinter.ttk import Style
def fix_forest_ttk(style: Style):
if style.theme_use() == "forest-light":
style.configure("ThemedText.TEntry", fieldbackground="#ffffff", textpadding=5, font="TkTextFont")
else:
style.configure("ThemedText.TEntry", fieldbackground="#313131", textpadding=5, font="TkTextFont")
# Example
app = Tk()
app.tk.call("source", "external-themes/forest-ttk-theme/forest-light.tcl")
Style().theme_use("forest-light")
fix_forest_ttk(Style())
app.mainloop()This project is inspired by Git GUI's native-theming technique.
This is an independent Python implementation; no GPL-licensed code is included.
The JetBrains Mono font used in the ttk-text logo is copyrighted by JetBrains and licensed under the SIL Open Font License 1.1.
See Contribution Guidelines for details.
This project is licensed under the MIT License, see the LICENSE file for details.


