Search code examples
ubuntutkinterthemesttkpython-3.7

How to make ttk use OS theme?


I'm running python 3.7 on kubuntu with the Workspace Theme 'Breeze Dark'. The tk widgets in my application adopt the OS's theme correctly but ttk widgets use something else.

Is there a way to get my ttk widgets to use the OS's theme?

import tkinter as tk
from tkinter import ttk


class App:

    def __init__(self, master):
        master.title("ttk vs tk widget example")
        # tk example gui
        tk_frame = tk.Frame(master)
        tk_frame.pack()

        self.tk_label = tk.Label(tk_frame, text="tk label:")
        self.var1 = tk.StringVar(value="tk entry")
        self.tk_entry = tk.Entry(tk_frame, textvariable=self.var1)
        self.tk_quit_button = tk.Button(tk_frame,
                                        text="Quit", width=20,
                                        command=tk_frame.quit)
        self.tk_button = tk.Button(tk_frame,
                                   text="tk button", width=20)
        self.tk_label.grid(row=0, column=0)
        self.tk_entry.grid(row=0, column=1)
        self.tk_button.grid(row=1, column=0, sticky='e')
        self.tk_quit_button.grid(row=1, column=1, sticky='e')

        separator = tk.Frame(height=2, bd=1, relief=tk.SUNKEN)
        separator.pack(fill=tk.X, padx=5, pady=15)

        # ttk example gui
        ttk_frame = ttk.Frame(master)
        ttk_frame.pack()

        self.ttk_label = ttk.Label(ttk_frame, text="ttk label:")
        self.var2 = tk.StringVar(value="ttk entry")
        self.ttk_entry = ttk.Entry(ttk_frame, textvariable=self.var2)
        self.ttk_quit_button = ttk.Button(ttk_frame,
                                          text="Quit", width=20,
                                          command=ttk_frame.quit)
        self.ttk_button = ttk.Button(ttk_frame,
                                     text="ttk button", width=20)
        self.ttk_label.grid(row=0, column=0)
        self.ttk_entry.grid(row=0, column=1)
        self.ttk_button.grid(row=1, column=0, sticky='e')
        self.ttk_quit_button.grid(row=1, column=1, sticky='e')


root = tk.Tk()
app = App(root)
root.mainloop()

Example of the ttk vs tk widgets:

Example of ttk vs tk

EDIT: So it's not a real fix but I can set the colors to be correct with:

tk_bg = self.tk_label.cget("background")
tk_fg = self.tk_label.cget("foreground")

self.ttk_label = ttk.Label(ttk_frame, text="ttk label:", 
                           background=tk_bg, foreground=tk_fg)

Solution

  • I am using XFCE desktop environment and even the tk widgets do not adapt to the theme I use which is not so surprising because XFCE is based on GTK GUI Toolkit so there is no reason for a GTK theme to influence a Tk theme.

    So you will need to change the theme of the GUI manually and the only way to set the colors of ttk widgets is through a ttk.Style:

    tk_bg = self.tk_label.cget("background")
    tk_fg = self.tk_label.cget("foreground")
    tk_entrybg = self.tk_entry.cget("background")
    
    style = ttk.Style(master)
    style.configure('TFrame', background=tk_bg)
    style.configure('TLabel', background=tk_bg, foreground=tk_fg)
    style.configure('TButton', background=tk_bg, foreground=tk_fg)
    style.configure('TEntry', background=tk_bg, fieldbackground=tk_entrybg, foreground=tk_fg)
    

    All ttk widgets are associated to a style (usually 'T + widget name', except for the Treeview for which there is no extra 'T'). And those styles are defined by the ttk theme you use. You can change theme with style.theme_use(<theme name>) and you can get the available themes with style.theme_names().