Switching values of tk.call() and ttk.Style().theme_use()

Question:

I have the following function that supposed to switch the theme of my GUI, but I’m dealing with a small issue. The theme switches the first time CheckButton pressed.

But trying it again getting the following errors:

_tkinter.TclError: Theme forest-light already exists

and:

_tkinter.TclError: Theme forest-dark already exists

code:

import tkinter as tk
from tkinter import ttk

themeTCL = 'forest-light.tcl'
themeFiles = 'forest-light'

window = tk.Tk()
window.title("TRANSMITTER")
window.geometry("1024x600")
window.tk.call('source', themeTCL)
ttk.Style().theme_use(themeFiles)

x_cordinate = int((window.winfo_screenwidth()/2) - (window.winfo_width()/2))
y_cordinate = int((window.winfo_screenheight()/2) - (window.winfo_height()/2))
window.geometry("+{}+{}".format(x_cordinate, y_cordinate))

var = tk.IntVar()
var.set(0)


def themeSwitch():
    global themeTCL
    global themeFiles
    if var.get() == 0:
        switch.config(text="Light Mode")
        themeTCL = 'forest-light.tcl'
        themeFiles = 'forest-light'
        window.tk.call('source', themeTCL)  # this line
        ttk.Style().theme_use(themeFiles)  # this line
    elif var.get() == 1:
        switch.config(text="Dark Mode")
        themeTCL = 'forest-dark.tcl'
        themeFiles = 'forest-dark'
        window.tk.call('source', themeTCL)  # this line
        ttk.Style().theme_use(themeFiles)  # this line


switch = ttk.Checkbutton(window, text="Light Mode", variable=var, command=themeSwitch, style="Switch")
switch.pack(side="top", fill="both", anchor="e", pady=(5, 5), padx=(5, 5))

window.mainloop()

I am no expert at this, but wondering if there is the way to configure the values tk.call() and ttk.Style().theme_use() so I can switch between dark and light mode.

Theme files are from: https://github.com/rdbende/Forest-ttk-theme

Any help would be appreciated. Thanks!

Asked By: Abtin

||

Answers:

try this

see, how self.tk.call(...) called only once for each theme during initialization and how self.style.theme_use(...) used to switch between the themes

import tkinter as tk
from tkinter import ttk


class App(tk.Tk):
    def __init__(self):
        super().__init__()

        self.title("TRANSMITTER")
        # self.geometry("1024x600")

        self.style = ttk.Style(self)

        # import the tcl files
        self.tk.call("source", "forest-light.tcl")
        self.tk.call("source", "forest-dark.tcl")

        # set the theme with the theme_use method
        # self.style.theme_use("forest-dark")

        # init window frame
        frame = ttk.Frame(self)

        # set frame to fill x and y axis and expand to fill window
        frame.pack(fill='both', expand=True)

        # init variable to hold the selected theme
        self.selected_theme = tk.StringVar()

        self.selected_theme.set("forest-dark")

        # create a label frame to hold the radio buttons
        theme_frame = ttk.LabelFrame(frame, text='Themes')

        # pack the label frame to the window with padding and sticky to the west side
        theme_frame.grid(padx=10, pady=10, ipadx=20, ipady=20, sticky='w')

        # create a radio button for each theme
        for theme_name in self.style.theme_names():
            rb = ttk.Radiobutton(
                theme_frame,
                text=theme_name,
                value=theme_name,
                variable=self.selected_theme,
                command=self.change_theme)

            rb.pack(expand=True, fill='both')

    def change_theme(self):
        self.style.theme_use(self.selected_theme.get())


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

Answered By: v0rs4
Categories: questions Tags: , , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.