Skip to content
Advertisement

How to change whole app’s theme when used within Class, Tkinter, ttkThemes, ThemedTk Python

Summary: I searched the internet about additional themes for tkinter. I found ttkthemes – ThemedTk option. However, my app is created within class. The difference between the example shown in the module website, the themedtk example is applied with root method. Here is the code:

import os
from tkinter import *
import tkinter as tk
from tkinter import ttk, filedialog
from PIL import ImageTk, Image
from ttkthemes import ThemedTk,THEMES
class App(tk.Tk):
def __init__(self):
    super().__init__()
    self.style = ThemedTk
    self.title(dil_sec[0])
    self.geometry("800x600")
    self.my_notebook = ttk.Notebook(self)
    self.my_notebook.pack(pady=15)
    self.my_menu = Menu(self)
    self.config(menu=self.my_menu)
    rec = None
    id_num = None
    self.first_lane = Menu(self.my_menu)
    self.my_menu.add_cascade(label=dil_sec[6], menu=self.first_lane)
    self.first_lane.add_command(label=dil_sec[2], command=self.customer_list)
    self.first_lane.add_command(label=dil_sec[1], command=lambda: self.customer_add(rec, id_num))
    self.second_lane = Menu(self.my_menu)
    self.my_menu.add_cascade(label=dil_sec[3], menu=self.second_lane)
    self.third_lane = Menu(self.my_menu)
    self.my_menu.add_cascade(label= dil_sec[65], menu=self.third_lane)
    self.third_lane.add_command(label=THEMES[0],command=lambda: self.stil_changer(still=THEMES[0]))
    self.third_lane.add_command(label=THEMES[1],command=lambda: self.stil_changer(still=THEMES[1]))

def stil_changer(self,still):
    print(still)
    self.style.set_theme(self,theme_name=still)

if __name__ == "__main__":
   app = App()
   app.mainloop()

When I run the application and the click the style and choose a style. I receive this error:

AttributeError: ‘_tkinter.tkapp’ object has no attribute ‘_toplevel’

It took so much time of me to solve it. Thanks in advance.

Advertisement

Answer

You forgot () in line

self.style = ThemedTk()

and later you have to remove self in

self.style.set_theme(theme_name=still)

and now it runs without error but still it doesn’t change theme.

Maybe it needs to use widgets from ttk.


EDIT:

You have to use ThemedTk in place of tk.Tk. And use directly self.set_theme()

And of course you need some widgets from ttk.

import tkinter as tk
import tkinter.ttk as ttk
from ttkthemes import ThemedTk

class App(ThemedTk):

    def __init__(self):
        super().__init__()
        
        self.geometry("800x600")
        
        self.my_notebook = ttk.Notebook(self)
        self.my_notebook.pack(pady=15, fill='both', expand=True)
        
        self.frame = ttk.Frame(self.my_notebook)
        self.my_notebook.add(self.frame, text='Buttons')
        for number in range(10):
            b = ttk.Button(self.frame, text=str(number))
            b.pack()
        
        self.my_menu = tk.Menu(self)
        self.config(menu=self.my_menu)
        
        self.first_lane = tk.Menu(self.my_menu)
        self.first_lane.add_command(label='a')
        self.first_lane.add_command(label='b')
        self.my_menu.add_cascade(label='Menu1', menu=self.first_lane)
        
        self.second_lane = tk.Menu(self.my_menu)
        self.my_menu.add_cascade(label='Menu2', menu=self.second_lane)
        
        self.third_lane = tk.Menu(self.my_menu)
        self.my_menu.add_cascade(label='Style', menu=self.third_lane)
        
        for item in sorted(self.get_themes()):
            self.third_lane.add_command(label=item, command=lambda name=item: self.changer_theme(name))
    
    def changer_theme(self, name):
        print('theme:', name)
        self.set_theme(name)
    
if __name__ == "__main__":
   app = App()
   app.mainloop()

enter image description here

Or you can use Tk with ThemedStyle (instead of ThemedTk)
and then you can set self.style = ThemedStyle()
but you have to use self.style.theme_use(name) instead of self.set_theme(name)

And it needs self.style.get_themes() instead of self.get_themes().

import tkinter as tk
import tkinter.ttk as ttk
from ttkthemes import ThemedStyle

class App(tk.Tk):

    def __init__(self):
        super().__init__()
        
        self.geometry("800x600")
        
        self.style = ThemedStyle()   # with Tk and ThemedStyle
        
        self.my_notebook = ttk.Notebook(self)
        self.my_notebook.pack(pady=15, fill='both', expand=True)
        
        self.frame = ttk.Frame(self.my_notebook)
        self.my_notebook.add(self.frame, text='Buttons')
        for number in range(10):
            b = ttk.Button(self.frame, text=str(number))
            b.pack()
        
        self.my_menu = tk.Menu(self)
        self.config(menu=self.my_menu)
        
        self.first_lane = tk.Menu(self.my_menu)
        self.first_lane.add_command(label='a')
        self.first_lane.add_command(label='b')
        self.my_menu.add_cascade(label='Menu1', menu=self.first_lane)
        
        self.second_lane = tk.Menu(self.my_menu)
        self.my_menu.add_cascade(label='Menu2', menu=self.second_lane)
        
        self.third_lane = tk.Menu(self.my_menu)
        self.my_menu.add_cascade(label='Style', menu=self.third_lane)
        
        #for item in sorted(self.get_themes()):       # with ThemedTk
        for item in sorted(self.style.get_themes()): # with Tk and ThemedStyle
            self.third_lane.add_command(label=item, command=lambda name=item: self.changer_theme(name))
    
    def changer_theme(self, name):
        print('theme:', name)
        #self.set_theme(name)        # with ThemedTk
        self.style.theme_use(name)   # with Tk and ThemedStyle
    
if __name__ == "__main__":
   app = App()
   app.mainloop()

I found screenshots for all themes: List of ttk Themes


OLD ANSWER

I have only working example with ttk.Buttons

import tkinter as tk
from tkinter import ttk
import ttkthemes

root = tk.Tk()

root.style = ttkthemes.ThemedStyle()
    
for i, name in enumerate(sorted(root.style.theme_names())):
    b = ttk.Button(root, text=name, command=lambda name=name:root.style.theme_use(name))
    b.pack(fill='x')

root.mainloop()

Default:

enter image description here

Blue:

enter image description here

Kroc:

enter image description here

Radiance or Ubuntu:

enter image description here

Winxpblue:

enter image description here


Source keep on GitHub: furas / python-examples / tkinter / themes-change-ttkthemes / buttons

User contributions licensed under: CC BY-SA
5 People found this is helpful
Advertisement