With the release of Version 4.0.0, the project is now officially known as "Reskinner". This is a re-write, focusing on improvements to the structure and API of the project.
- Full support for FreeSimpleGUI is here. Thanks to @deajan for the contribution and bringing it to my notice.
- The entire project has been rewritten from scratch for better maintainability, extensibility, and performance.
- The
animated_reskinfunction is no more... because thereskinfunction itself has animation parameters baked in now. - The API for
reskinhas been improved to require only 2 parameters; the window, and the desired theme. The project's minimum supported Python version is now 3.8.Python 3.7 support is back from 4.0.1- Mentions of
HSVinterpolation in the code have been corrected; it'sHSL.
Reskinner is a powerful library for PySimpleGUI and FreeSimpleGUI, enabling dynamic theme switching at runtime without window recreation. It provides a seamless way to update your application's look and feel on the fly.
- Dynamic theme switching without window recreation
- Supports both PySimpleGUI and FreeSimpleGUI
- Easy integration with existing applications
- Precise control over theme transitions with animations and 3 supported interpolation modes.
- Lightweight and dependency-minimal
# For PySimpleGUI pip install "reskinner[psg]" # For FreeSimpleGUI pip install "reskinner[fsg]"# Install uv if not already installed pip install uv # For PySimpleGUI uv add reskinner[psg] # For FreeSimpleGUI uv add reskinner[fsg]from random import choice import PySimpleGUI as sg # or import FreeSimpleGUI as sg from reskinner import reskin # Create a simple window layout = [ [sg.Text("Hello, Reskinner!")], [sg.Button("Change Theme"), sg.Button("Exit")] ] window = sg.Window("Reskinner Demo", layout) themes = sg.theme_list() current_theme = sg.theme() def change_theme(): new_theme = choice([t for t in themes if t != current_theme]) reskin(window, new_theme) return new_theme while True: event, values = window.read() if event in (sg.WIN_CLOSED, 'Exit'): break if event == "Change Theme": current_theme = change_theme() window.close()from reskinner import reskin import PySimpleGUI as sg # Apply a new theme instantly reskin(window=my_window, new_theme="DarkBlue3", theme_function=sg.theme)Reskinner supports three different interpolation modes for theme transitions; hsl, hue, and rgb (default):
from reskinner import reskin import PySimpleGUI as sg # Smooth, animated color transition using HSL interpolation reskin( window=window, new_theme="DarkAmber", theme_function=sg.theme, duration_in_milliseconds=800, interpolation_mode="hsl", )Customize whether specific elements are styled during reskinning:
from reskinner import reskin import PySimpleGUI as sg # Skip elements you don't want to restyle reskin( window=window, new_theme="LightGreen", theme_function=sg.theme, element_filter=lambda e: e.key != "skip_me" )This uses one of Reskinner’s built-in easing functions (based on https://easing.net) for a smooth, natural animation.
from reskinner import reskin import PySimpleGUI as sg # Apply a theme with animation and built-in easing reskin( window=window, new_theme="DarkBlue", duration=1000, # milliseconds interpolation_mode="rgb", easing_function="ease_in_out_sine", )Any callable accepting a float between 0 and 1, and returning a float in the same range, is valid as a custom easing function. In this example, we use the golden ratio as our easing function
from math import pow from reskinner import reskin import PySimpleGUI as sg def golden_ease_out(t: float) -> float: phi = (1 + 5 ** 0.5) / 2 # ≈ 1.618 return 1 - pow(1 - t, phi) # Apply a theme with golden-ratio-based easing reskin( window=window, new_theme="DarkGreen5", duration=1000, interpolation_mode="rgb", easing_function=golden_ease_out, )- Python 3.8+
- PySimpleGUI 4.60.0+ or FreeSimpleGUI 5.0.0+ (Tkinter variant only; Reskinner doesn't support *Qt, *Wx, or *Web variants)
- Tkinter (included with Python)
This project is licensed under the MIT License - see the LICENSE file for details.
- The PySimpleGUI and FreeSimpleGUI communities
- All contributors who have helped improve Reskinner
Reskinner runs through each element in a window, then by relying on the element.widget interface to access the underlying Tkinter object, it applies style changes to the window.
Like Unda, I created Reskinner to be a part/feature of a desktop application which I'm developing, however, I decided to open-source it, as I imagined other developers would find such functionality useful in their projects as well.
Development began on Monday 15th August 2022.
I didn't want it to go against the built-in conventions of theme and look_and_feel that PySimpleGUI has.
