Вопрос или проблема
Я пытаюсь настроить свое приложение на CustomTkinter
с помощью двух вещей:
- Настроенного стиля (для определения цветов, шрифтов…)
- Настроенных виджетов, унаследующих настроенный стиль
Настроенный стиль определен как класс, который принимает аргумент для выбора некоторых цветов или других цветов:
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)
Почему я кодировал это так?
- Настроенные виджеты избавляют меня от необходимости указывать некоторые параметры каждый раз (например, настройки
grid
). - Стиль с аргументом позволяет мне изменять все цвета, шрифты… приложения, не меняя все параметры виджетов (например, настройки
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
.