Python Tkinter – Установка пользовательского стиля для приложения

Вопрос или проблема

Я пытаюсь настроить свое приложение на CustomTkinter с помощью двух вещей:

  1. Настроенного стиля (для определения цветов, шрифтов…)
  2. Настроенных виджетов, унаследующих настроенный стиль

Настроенный стиль определен как класс, который принимает аргумент для выбора некоторых цветов или других цветов:

class Style():
    def __init__(self, selected_style):
        match selected_style:
            case "style1":
                self.colors = ["#3d3d3d", "#5c5c5c"]
            case "style2":
                self.colors = ["#c6c6c6", "#ececec"]

Настроенные виджеты затем унаследуют стиль. В качестве примера приведен виджет кнопки:

from customtkinter import CTkButton

class MyButton(CTkButton, Style):
    def __init__(self, master, style, text):
        Style.__init__(self, style)
        CTkButton.__init__(self, master, text=text, fg_color=self.colours[1])
        self.grid(sticky="WE", padx=8, pady=8)

Почему я кодировал это так?

  1. Настроенные виджеты избавляют меня от необходимости указывать некоторые параметры каждый раз (например, настройки grid).
  2. Стиль с аргументом позволяет мне изменять все цвета, шрифты… приложения, не меняя все параметры виджетов (например, настройки grid).

В чем проблема?

При инстанциировании виджета требуется передать аргумент стиля (“style1” или “style2”). Он определяется при запуске приложения, и мне затем нужно передать его через все приложение к каждому виджету.

Как мне избежать передачи аргумента стиля через все приложение?

Я понимаю, что, возможно, мне нужно существенно изменить мой код…

Один удобный способ – использовать переменную класса. Назовите ее default_style:

class Style:
    default_style="style1"
    def __init__(self, selected_style=None):
        if selected_style is None:
            self.selected_style = self.default_style
        else:
            self.selected_style = selected_style
        match self.selected_style:
            case "style1":
                self.colors = ["#3d3d3d", "#5c5c5c"]
            case "style2":
                self.colors = ["#c6c6c6", "#ececec"]

Если вы установите default_style в начале программы с помощью строки, подобной этой:

Style.default_style="style2"

то этот стиль будет использоваться повсюду в программе.

Если вы хотите переопределить стиль только для одного класса виджета, передайте ненулевой аргумент в конструктор Style:

class MySpecialButton(CTkButton, Style):
    def __init__(self, master, text):
        Style.__init__(self, 'style2')
        CTkButton.__init__(self, master, text=text, fg_color=self.colours[1])
        self.grid(sticky="WE", padx=8, pady=8)

в противном случае просто сделайте это:

class MyButton(CTkButton, Style):
    def __init__(self, master, text):
        Style.__init__(self)
        CTkButton.__init__(self, master, text=text, fg_color=self.colours[1])
        self.grid(sticky="WE", padx=8, pady=8)

Ответ или решение

Для решения вашей задачи по настройке стилей в приложении на основе библиотеки CustomTkinter, можно использовать подход с классом, который будет хранить дефолтный стиль, а также возможность переопределения этого стиля для определённых виджетов. Ниже приведены шаги для реализации этой идеи.

Шаг 1: Определение класса Style

Мы создадим класс Style, который будет содержать как дефолтный стиль, так и логику для определения цветов в зависимости от выбранного стиля.

class Style:
    default_style = "style1"  # Дефолтный стиль

    def __init__(self, selected_style=None):
        if selected_style is None:
            self.selected_style = self.default_style
        else:
            self.selected_style = selected_style

        match self.selected_style:
            case "style1":
                self.colors = ["#3d3d3d", "#5c5c5c"]
            case "style2":
                self.colors = ["#c6c6c6", "#ececec"]
            case _:
                raise ValueError("Неизвестный стиль: {}".format(self.selected_style))

Шаг 2: Определение кастомных виджетов

Теперь мы можем создавать классы для наших кастомных виджетов, используя класс Style. Мы будем передавать стиль в конструктор виджета или использовать дефолтный стиль, если аргумент не указан.

Пример обычной кнопки

from customtkinter import CTkButton

class MyButton(CTkButton, Style):
    def __init__(self, master, text):
        Style.__init__(self)  # Использует дефолтный стиль
        CTkButton.__init__(self, master, text=text, fg_color=self.colors[1])
        self.grid(sticky="WE", padx=8, pady=8)

Пример специальной кнопки с переопределённым стилем

class MySpecialButton(CTkButton, Style):
    def __init__(self, master, text):
        Style.__init__(self, 'style2')  # Использует стиль2
        CTkButton.__init__(self, master, text=text, fg_color=self.colors[1])
        self.grid(sticky="WE", padx=8, pady=8)

Шаг 3: Установка стиля в начале приложения

Перед тем как создать любые виджеты, вы можете установить желаемый стиль по умолчанию в начале программы:

Style.default_style = "style2"

Примечание

Таким образом, вам не нужно каждый раз передавать стиль через весь проект. Вы просто используете Style.__init__(self) в тех местах, где хотите использовать дефолтный стиль. Если вы хотите использовать другой стиль для конкретного виджета, вы можете передать нужное значение в конструктор класса Style.

Заключение

Данный подход позволяет более гибко управлять стилями, не искажая основную логику приложения и сохраняя его структуру. Надеюсь, это поможет вам в дальнейшей разработке вашего приложения на CustomTkinter.

Оцените материал
Добавить комментарий

Капча загружается...