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.