Python Tkinter resize all ttkbootstrap or ttk Button padding for a specific style, applied to all themes

37 views Asked by At

I want to alter padding for all buttons using a particular style (danger). For some reason this change is only applied to the currently active theme, switching themes reverts the Button padding to default. You can see the issue by running the following and switching themes ...

import tkinter as tk
from tkinter import ttk
import ttkbootstrap as tb

def change_theme(theme, style): style.theme_use(theme.lower().replace(" ", ""))

def display_text(label_text, entry_text): label_text.set(entry_text.get())

def setup_ui(style):
    root = style.master

    danger = tb.Style()
    danger.configure('danger.TButton', padding=0) # Why does this only apply to the first theme?

    theme_names_titlecase = [name.replace('_', ' ').title() for name in style.theme_names() if name.lower() in ['darkly', 'simplex']]
    default_theme = 'darkly'
    current_theme = tk.StringVar(value=default_theme.capitalize())
    
    theme_combo = ttk.Combobox(root, textvariable=current_theme, values=theme_names_titlecase, width=50)
    theme_combo.pack(pady=0, side=tk.TOP)
    theme_combo.bind("<<ComboboxSelected>>", lambda e: change_theme(current_theme.get(), style))

    tb.Button(root, text='Text', bootstyle='danger.TButton').pack(side=tk.TOP, padx=0, pady=0)
    tb.Button(root, text='Text', bootstyle='info.TButton').pack(side=tk.TOP, padx=0, pady=0)

    return root

if __name__ == "__main__":
    default_theme = 'darkly'
    style = tb.Style(theme=default_theme)
    root = setup_ui(style)
    root.mainloop()

What I want to know is :

  1. Why are my changes to 'danger.TButton' only applied to the current theme?
  2. Can I fix this so all 'danger.TButton' s have no padding regardless of theme?

Note: using all ttk widgets and Styles has the same result so the answer relates to ttk not ttkbootstrap particularly.

Many thanks.

2

There are 2 answers

1
Muhammed Samed Özmen On BEST ANSWER

The main reason is this part and configuring tb.Style() within the setup_ui(). It means that the configuration you're setting for danger.TButton is only associated with the instance of tb.Style(), So,when u try to change your theme, a new instance of tb.Style() is created internally by ttkbootstrap, and your custom configuration is not carried over to this new instance.

danger = tb.Style()
danger.configure('danger.TButton', padding=0) # Why does this only apply to the first theme?

By configuring danger.TButton directly on the main instance of tb.Style(), your custom configuration will be applied consistently across all themes. Here is solution for your code:

import tkinter as tk
from tkinter import ttk
import ttkbootstrap as tb

def change_theme(theme, style):style.theme_use(theme.lower().replace(" ", ""))

def display_text(label_text, entry_text):label_text.set(entry_text.get())

def setup_ui(style):
    root = style.master

    theme_names_titlecase = [name.replace('_', ' ').title() for name in style.theme_names() if name.lower() in ['darkly', 'simplex']]
    default_theme = 'darkly'
    current_theme = tk.StringVar(value=default_theme.capitalize())
    
    theme_combo = ttk.Combobox(root, textvariable=current_theme, values=theme_names_titlecase, width=50)
    theme_combo.pack(pady=0, side=tk.TOP)
    theme_combo.bind("<<ComboboxSelected>>", lambda e: change_theme(current_theme.get(), style))

    tb.Button(root, text='Text', bootstyle='danger.TButton').pack(side=tk.TOP, padx=0, pady=0)
    tb.Button(root, text='Text', bootstyle='info.TButton').pack(side=tk.TOP, padx=0, pady=0)

    return root

if __name__ == "__main__":
    default_theme = 'darkly'
    style = tb.Style(theme=default_theme)

    style.configure('danger.TButton', padding=0) # Why does this only apply to the first theme?


    root = setup_ui(style)
    root.mainloop()
0
Inyoka On

The style is apparently applied only to the theme used when the program is launched.

Therefore when the theme is changed to the non-default theme, the padding adjustment needs to be re-applied. In this example to solve the problem I had to modify the 'change_theme' function.

def change_theme(theme, style): 
    style.theme_use(theme.lower().replace(" ", ""))
    style.configure('danger.TButton', padding=0)

This reapplies the padding change to every new theme applied.