products:pyrog:tutorials:dev:main
Различия
Показаны различия между двумя версиями страницы.
| Предыдущая версия справа и слеваПредыдущая версияСледующая версия | Предыдущая версия | ||
| products:pyrog:tutorials:dev:main [2026/06/05 00:54] – ironmesh | products:pyrog:tutorials:dev:main [2026/08/01 23:09] (текущий) – ironmesh | ||
|---|---|---|---|
| Строка 1: | Строка 1: | ||
| ====== Руководство по разработке ====== | ====== Руководство по разработке ====== | ||
| - | Для разработки собственного приложения нужно иметь минимум базовые навыки разработки на Python и PySide6. | + | Для разработки собственного приложения нужно иметь минимум базовые навыки разработки на Python и PySide6. |
| - | ==== 2.1 Скачивание исходников и подготовка IDE к работе ==== | ||
| - | Скачайте исходные файлы программы из [[https:// | + | ===== 1. Быстрый старт |
| - | Теперь, | + | ==== 1.1 Скачивание исходников и подготовка |
| - | Можете выключить ненужные плагины, чтобы не мешали. | + | Скачайте исходные файлы программы из [[https:// |
| - | ==== 2.2 Анатомия плагина | + | Теперь, |
| - | В Python пакетом является папка, которая содержит в себе файл с именем '' | + | > |
| + | |||
| + | ==== 1.2 Анатомия плагина ==== | ||
| + | |||
| + | В Python пакетом является папка, которая содержит в себе файл с именем | ||
| <code -> | <code -> | ||
| Строка 28: | Строка 31: | ||
| </ | </ | ||
| - | В файле '' | + | В файле '' |
| <code python> | <code python> | ||
| Строка 41: | Строка 44: | ||
| </ | </ | ||
| - | В файле manifest.json хранится информация о плагине, | + | В файле |
| <code json> | <code json> | ||
| Строка 69: | Строка 72: | ||
| </ | </ | ||
| - | Пояснение к атрибутам: | + | Пояснения к атрибутам: |
| - | * **name** | + | ^ Поле ^ Описание ^ Пример ^ |
| - | | + | | **name** |
| - | | + | | **description** |
| - | | + | | **project_page_url** |
| - | | + | | **manual_url** |
| - | | + | | **version** |
| - | | + | | **version_status** |
| - | | + | | **init_release_date** |
| - | | + | | **update_date** |
| - | | + | | **developer** |
| - | | + | | **developer_email** |
| - | | + | | **developer_webpage** |
| - | | + | | **repository_url** |
| - | | + | | **forum_url** |
| - | | + | | **dependencies** |
| + | | **source_language** | ||
| - | Папка '' | + | Папка '' |
| Двигаемся дальше. Заглянем в файл '' | Двигаемся дальше. Заглянем в файл '' | ||
| Строка 145: | Строка 149: | ||
| </ | </ | ||
| - | Все настройки помещаются в классе '' | + | Все настройки помещаются в классе '' |
| * **name** - имя свойства, | * **name** - имя свойства, | ||
| Строка 151: | Строка 155: | ||
| * **tooltip** - всплывающая подсказка с описанием, | * **tooltip** - всплывающая подсказка с описанием, | ||
| * **show_reset_btn** - (может быть не у всех Свойств) задает видимость кнопки сброса значения Свойства, | * **show_reset_btn** - (может быть не у всех Свойств) задает видимость кнопки сброса значения Свойства, | ||
| - | * **widget_enabled** - задает активность виджета свойства, | + | * **widget_enabled** - задает активность виджета свойства, |
| + | |||
| + | Добавьте в тело класса атрибуты с нужными Cвойствами. Атрибуты других типов тоже допустимы. Служебные атрибуты имеют префикс '' | ||
| ^ Имя класса свойства ^ Тип данных ^ Пояснение ^ | ^ Имя класса свойства ^ Тип данных ^ Пояснение ^ | ||
| Строка 159: | Строка 165: | ||
| | BoolProperty | bool | Булевое значение | | | BoolProperty | bool | Булевое значение | | ||
| | ColorProperty | str | Строка с кодом цвета в формате HEX, например, | | ColorProperty | str | Строка с кодом цвета в формате HEX, например, | ||
| - | | FontProperty | | + | | FontProperty | tuple[str, str, int] |
| | ComboBoxProperty | int | Индекс выбранного элемента списка | | | ComboBoxProperty | int | Индекс выбранного элемента списка | | ||
| | StringProperty | str | Строка | | | StringProperty | str | Строка | | ||
| Строка 166: | Строка 172: | ||
| | FilePathProperty | str | Строка, | | FilePathProperty | str | Строка, | ||
| | FilePathListProperty | tuple[tuple[str, | | FilePathListProperty | tuple[tuple[str, | ||
| + | | PlainTextProperty | str | Представляет строковое значение. Отличается от **StringListProperty** тем, что предоставляет многострочное поле ввода | | ||
| + | | DateTimeProperty | str | Дата и время в виде строки, | ||
| - | Чтобы использовать свойства в коде, просто импортируем класс Settings, и вызываем свойство '' | + | Чтобы использовать свойства в коде, просто импортируем класс |
| Итак, вы познакомились с устройством плагина и этих минимальных сведений достаточно для разработки своих программ, | Итак, вы познакомились с устройством плагина и этих минимальных сведений достаточно для разработки своих программ, | ||
| Строка 173: | Строка 181: | ||
| Как вы видите для того чтобы работать с Pyrog нужно объявить специальный класс плагина, | Как вы видите для того чтобы работать с Pyrog нужно объявить специальный класс плагина, | ||
| - | ===== 3. Расширяем познания ===== | + | ===== 2. Расширяем познания ===== |
| В предыдущем разделе мы познакомились с основами разработки плагинов, | В предыдущем разделе мы познакомились с основами разработки плагинов, | ||
| Строка 186: | Строка 194: | ||
| * других нюансах и особенностях. | * других нюансах и особенностях. | ||
| - | ==== 3.1 Жизненный цикл плагина ==== | + | ==== 2.1 Жизненный цикл плагина ==== |
| - | Когда пользователь запускает Менеджер, | + | Когда пользователь запускает Менеджер, |
| * '' | * '' | ||
| * '' | * '' | ||
| - | Когда загружается контейнер свойств, | + | Когда загружается контейнер свойств, |
| Если пользователь деактивирует плагин, | Если пользователь деактивирует плагин, | ||
| - | ==== 3.2 Ваш универсальный помощник ==== | + | ==== 2.2 Ваш универсальный помощник ==== |
| - | Для общения с Менеджером используйте класс | + | Для общения с Менеджером используйте класс |
| - | Данный класс предоставляет следующие методы: | + | === 2.2.1 Методы |
| - | ^ Метод ^ Выполняемые действия ^ | + | **save_settings_parameters()** |
| - | | save_settings_parameters | Сохраняет параметры Свойств, | + | |
| - | | save_settings_values | + | Сохраняет параметры Свойств, |
| - | | plugin_dir_abspath | + | |
| - | | plugin_localstorage_dir_abspath | + | **save_settings_values()** |
| + | |||
| + | Сохраняет значения Свойств, | ||
| + | |||
| + | **plugin_dir_abspath()** | ||
| + | |||
| + | Возвращает строку с абсолютным путем к папке плагина | ||
| + | |||
| + | **plugin_localstorage_dir_abspath()** | ||
| + | |||
| + | Возвращает строку с абсолютным путем к индивидуальной папке в локальном хранилище Менеджера ('' | ||
| + | |||
| + | **set_menu()** | ||
| + | |||
| + | Устанавливает меню (объект класса [[https:// | ||
| + | |||
| + | Для того чтобы установить собственное меню, передайте аргументу //menu// объект класса **QMenu**, а аргументу // | ||
| + | |||
| + | * ''" | ||
| + | * ''" | ||
| + | * ''" | ||
| + | * ''" | ||
| + | |||
| + | В качестве демонстрации посмотрите на изображение ниже, здесь демонстрируются варианты использовать контекстных меню вкладок\\ {{ https:// | ||
| + | |||
| + | Описания обозначений: | ||
| + | |||
| + | - Встроенное меню | ||
| + | - Переопределенное встроенное меню | ||
| + | - Встроенное меню + Пользовательское меню в начале | ||
| + | - Встроенное меню + Пользовательское меню в конце | ||
| + | - Встроенное меню + Пользовательское меню в начале и в конце | ||
| + | |||
| + | Чтобы удалить ранее установленное меню - передайте аргументу //menu// объект **None**. | ||
| + | |||
| + | **get_menu()** | ||
| + | |||
| + | Возвращает ранее установленное меню в указанное позиции, | ||
| + | |||
| + | === 2.2.2 Сигналы === | ||
| Helper также имеет ряд сигналов, | Helper также имеет ряд сигналов, | ||
| Строка 216: | Строка 263: | ||
| | app_closing | Пользователь закрыл Менеджер. Отправляется до того, как программа завершит работу. Полезен для безопасного завершения сессии. | | | app_closing | Пользователь закрыл Менеджер. Отправляется до того, как программа завершит работу. Полезен для безопасного завершения сессии. | | ||
| | settings_editing_starting | Пользователь открыл пользовательские настройки. Отправляется перед тем как окно редактирования будет выведено на экран. Полезно когда нужно подготовить программу к изменению настроек. | | | settings_editing_starting | Пользователь открыл пользовательские настройки. Отправляется перед тем как окно редактирования будет выведено на экран. Полезно когда нужно подготовить программу к изменению настроек. | | ||
| - | | settings_editing_finished | Пользователь завершил редактирование настроек. \\ Возвращает булевое значение, | + | | settings_editing_finished | Пользователь завершил редактирование настроек. \\ Возвращает булевое значение, |
| - | + | ||
| - | В любом случае вы можете отслеживать изменения значений Свойств на лету. | + | |
| Весь код в Менеджере выполняется синхронно, | Весь код в Менеджере выполняется синхронно, | ||
| - | ==== 3.3 Делаем локализацию интерфейса ==== | + | |
| + | ==== 2.3 Делаем локализацию интерфейса ==== | ||
| Итак, для разблокировки механизма интернационализации нужно в файле манифеста указать исходный язык, например, | Итак, для разблокировки механизма интернационализации нужно в файле манифеста указать исходный язык, например, | ||
| - | ==== 3.3.1 Языковые константы ==== | + | ==== 2.3.1 Языковые константы ==== |
| - | Языковые константы (ЯК) - это объекты, | + | Языковые константы (ЯК) - это объекты, |
| <code python> | <code python> | ||
| Строка 245: | Строка 291: | ||
| * контекст | * контекст | ||
| * текст константы | * текст константы | ||
| - | * (опционально) строка идентификатор, | + | * (опционально) строка идентификатор, |
| Извлечь перевод (при его наличии, | Извлечь перевод (при его наличии, | ||
| Строка 253: | Строка 299: | ||
| </ | </ | ||
| - | У ЯК переопределен метод '' | + | У ЯК переопределен метод '' |
| <code python> | <code python> | ||
| Строка 267: | Строка 313: | ||
| </ | </ | ||
| - | преобразование производится при вызове экземпляра как функции, | + | преобразование производится при вызове экземпляра как функции, |
| <code python> | <code python> | ||
| Строка 289: | Строка 335: | ||
| </ | </ | ||
| - | этой | + | функции |
| - | Языковые константы поддерживают перевод для множественных форм числительных, | + | Языковые константы поддерживают перевод для множественных форм числительных, |
| <code python> | <code python> | ||
| Строка 308: | Строка 354: | ||
| </ | </ | ||
| - | Обращаю ваше внимание, | + | Обращаю ваше внимание, |
| - | ==== 3.3.2 Процедура перевода ==== | + | ==== 2.3.2 Процедура перевода ==== |
| - | Теперь, | + | Теперь, |
| Рассмотрим подробнее, | Рассмотрим подробнее, | ||
| - | | + | |
| - | | + | |
| - | | + | |
| - | | + | |
| - | | + | |
| - | Итак, нам как разработчикам плагинов нужно сосредоточиться на шаге 4, когда | + | Итак, нам как разработчикам плагинов нужно сосредоточиться на шаге 4, когда на нужно |
| <code python> | <code python> | ||
| Строка 340: | Строка 386: | ||
| def _on_retranslate(self, | def _on_retranslate(self, | ||
| retranslate_nested_langconstants(lang_consts) | retranslate_nested_langconstants(lang_consts) | ||
| + | |||
| self._file_list_input.set_file_filter(f" | self._file_list_input.set_file_filter(f" | ||
| self._toolBox.setItemText(0, | self._toolBox.setItemText(0, | ||
| Строка 348: | Строка 395: | ||
| self._clear_btn.setText(lang_consts.CLEAR()) | self._clear_btn.setText(lang_consts.CLEAR()) | ||
| self._generate_btn.setText(lang_consts.GENERATE()) | self._generate_btn.setText(lang_consts.GENERATE()) | ||
| - | | + | |
| </ | </ | ||
| - | В нем с помощью функции | + | В нем с помощью функции |
| - | Когда мы используем QtDesigner для создания форм | + | Когда мы используем QtDesigner для создания форм, то в коде формы, которую он генерирует есть метод '' |
| - | ==== 3.3.3 Подготовка словарей ==== | + | ==== 2.3.3 Подготовка словарей ==== |
| После того как работа над кодом плагина закончена, | После того как работа над кодом плагина закончена, | ||
| - | Для создания TS файлов из исходников есть встроенная утилита TS generator. Перейдите в её настройки и установите адрес папки, в которой будут сохраняться временные файлы, и путь к файлу lupdate, он находится в папке, где устанавливаются пакеты Python, для Windows это '' | + | Для создания TS файлов из исходников есть встроенная утилита TS generator. При первом применении перейдите в её настройки и установите адрес папки, в которой будут сохраняться временные файлы, и путь к файлу |
| * Python файлы ('' | * Python файлы ('' | ||
| * Файл манифеста ('' | * Файл манифеста ('' | ||
| - | * Файлы форм, созданных в QtDesigner ('' | + | * Файлы форм, созданных в QtDesigner ('' |
| + | |||
| + | В разделе **Сохранить в** укажите путь к TS файлам, | ||
| - | * утилита импортирует исходные файлы Python и выполняет их код для поиска в них языковых констант, | + | <WRAP center round important 80%> |
| + | Утилита импортирует исходные файлы Python и выполняет их код для поиска в них языковых констант, | ||
| + | </ | ||
| - | Итак, мы получили файлы с исходными текстами, | + | Итак, мы получили файлы с исходными текстовыми данными, теперь нужно их перевести на целевой язык. Запускаем утилиту Qt Linguist и открываем наши TS-файлы. При первой загрузке нужно выбрать язык оригинала и язык перевода. У утилиты есть одна фишка - можно открыть сразу несколько TS файлов, |
| В разделе **Контекст** мы видим, что все текстовые данные сгруппированы в соответствии с тем текстом, | В разделе **Контекст** мы видим, что все текстовые данные сгруппированы в соответствии с тем текстом, | ||
| Строка 375: | Строка 426: | ||
| Также есть возможность скомпилировать файлы переводов утилитой lrelease, можно прочитать информацию по ней [[https:// | Также есть возможность скомпилировать файлы переводов утилитой lrelease, можно прочитать информацию по ней [[https:// | ||
| - | Сейчас можно | + | <WRAP center round tip 80%> |
| + | Можно | ||
| + | </ | ||
| - | ==== 3.4 Система свойств ==== | + | ==== 2.4 Система свойств ==== |
| - | ==== 3.4.1 Как работать со Свойствами ==== | + | ==== 2.4.1 Как работать со Свойствами ==== |
| - | Свойство в контексте Pyrog это программная единица, | + | Свойство в контексте Pyrog это программная единица, |
| Рассмотрим строение Свойства на конкретном примере '' | Рассмотрим строение Свойства на конкретном примере '' | ||
| Строка 391: | Строка 444: | ||
| Список аргументов-параметров следующий | Список аргументов-параметров следующий | ||
| - | ^ Параметр ^ Тип ^ Описание | + | ^ Параметр ^ Тип ^ Описание | |
| - | | default_value | float | значение по умолчанию | | | + | | default_value | '' |
| - | | name | str | LangConstant | имя Свойства, | + | | name | '' |
| - | | minimum | float | минимальное значение | | | + | | minimum | '' |
| - | | maximum | float | максимальное значение | | | + | | maximum | '' |
| - | | single_step | float | единичный шаг, шаг изменения значения при нажатии на кнопки виджета QDoubleSpinBox | + | | single_step | '' |
| - | | decimals | int | количество знаков после запятой | + | | decimals | '' |
| - | | tooltip | str | LangConstant | всплывающая подсказка с описание свойства | | + | | tooltip | '' |
| - | | show_reset_btn | bool | флаг того, будет ли показана кнопка сброса значения до дефолтного рядом с виджетом, | + | | show_reset_btn | '' |
| - | Как ранее было сказано, | + | Как ранее было сказано, |
| - | **Реакция значения Свойства на изменения параметров** Значение Свойства должно находиться в диапазоне, | + | === Реакция значения Свойства на изменения параметров === |
| - | **Как работает | + | Значение Свойства должно находиться в диапазоне, установленном параметрами, таким образом если '' |
| - | **Сохранение параметров Свойств в базе данных Менеджера** Если по каким-то причинам вам нужно изменять значения параметров и при следующем запуске плагина их нужно восстановить, | + | === Как работает мягкая валидация === |
| - | **Как получить уведомление | + | Вы уже видели, что значение изменяется в соответствии с установленным диапазоном |
| - | **Как получить доступ к графическому интерфейсу** Каждое Свойство имеет метод '' | + | === Сохранение параметров Свойств в базе данных Менеджера |
| - | ==== 3.4.2 Как работать с контейнером свойств ==== | + | Если по каким-то причинам вам нужно изменять значения параметров и при следующем запуске плагина их нужно восстановить, |
| + | |||
| + | === Как получить уведомление об изменении значения | ||
| + | |||
| + | Свойства поддерживают сигналы, | ||
| + | |||
| + | === Как получить доступ к графическому интерфейс === | ||
| + | |||
| + | Каждое Свойство имеет метод '' | ||
| + | |||
| + | ==== 2.4.2 Как работать с контейнером свойств ==== | ||
| По своей сути Контейнер свойств это обычный класс, унаследованный от '' | По своей сути Контейнер свойств это обычный класс, унаследованный от '' | ||
| Строка 438: | Строка 501: | ||
| from .settings import Settings | from .settings import Settings | ||
| - | print(Settings.int_property.value) # вывести значение | + | print(Settings.int_property.value) # вывести значение |
| - | Settings.int_property.value = 7 # изменить значение | + | Settings.int_property.value = 7 # изменить значение |
| - | print(Settings.int_property.default_value) # вывести дефольное значение | + | print(Settings.int_property.default_value) # вывести дефолтное значение |
| - | Settings.int_property.default_value = 9 # измениим дефолтное значение | + | Settings.int_property.default_value = 9 # изменить дефолтное значение |
| </ | </ | ||
| - | Чтобы получить уведомление об изменение значений используйте нотификатор | + | Чтобы получить уведомление об изменении значений используйте нотификатор |
| <code python> | <code python> | ||
| Строка 467: | Строка 530: | ||
| Если нотификатор стал не нужен, то удалите его методом '' | Если нотификатор стал не нужен, то удалите его методом '' | ||
| - | **Как получить доступ к общему графическому интерфейсу Свойств** Контейнер свойств может отрендерить графический интерфейс, | + | === Как получить доступ к общему графическому интерфейсу Свойств |
| + | |||
| + | Контейнер свойств может отрендерить графический интерфейс, | ||
| Дефолтный интерфейс дает возможность фильтровать Свойства по имени, а также сбросить значения до дефолтных для всех Свойств. Данный интерфейс можно переопределить, | Дефолтный интерфейс дает возможность фильтровать Свойства по имени, а также сбросить значения до дефолтных для всех Свойств. Данный интерфейс можно переопределить, | ||
| - | **Как пакетно извлечь/ | + | === Как пакетно извлечь/ |
| + | |||
| + | Например, | ||
| * '' | * '' | ||
| Строка 481: | Строка 548: | ||
| * '' | * '' | ||
| - | ==== 3.4.3 Как разработать собственное Свойство ==== | + | ==== 2.4.3 Как разработать собственное Свойство ==== |
| - | Может так случиться, | + | Может так случиться, |
| - | **Шаг 1** Объявляем класс и создаем сигнал. Имя сигнала не изменять! | + | **Шаг 1.** Объявляем класс и создаем сигнал. Имя сигнала не изменять! |
| <code python> | <code python> | ||
| class BoolListProperty(Property): | class BoolListProperty(Property): | ||
| - | value_changed = Signal(tuple) | + | value_changed = Signal(tuple) |
| </ | </ | ||
| - | **Шаг 2** Задание схемы параметров Свойства, | + | **Шаг 2.** Задание схемы параметров Свойства, |
| <code python> | <code python> | ||
| Строка 534: | Строка 601: | ||
| * '' | * '' | ||
| * '' | * '' | ||
| - | * '' | + | * '' |
| Рассмотрим функцию-валидатор | Рассмотрим функцию-валидатор | ||
| Строка 542: | Строка 609: | ||
| </ | </ | ||
| - | параметр '' | + | параметр '' |
| - | **Шаг 3** Создаем свойства для всех параметров, | + | **Шаг 3.** Создаем свойства для всех параметров, |
| <code python> | <code python> | ||
| items = create_param_property(" | items = create_param_property(" | ||
| - | |||
| tooltip = create_param_property(" | tooltip = create_param_property(" | ||
| - | |||
| name = create_param_property(" | name = create_param_property(" | ||
| - | + | show_reset_btn = create_param_property(" | |
| - | show_reset_btn = create_param_property(" | + | |
| default_value = create_param_property(" | default_value = create_param_property(" | ||
| </ | </ | ||
| Строка 565: | Строка 628: | ||
| * '' | * '' | ||
| - | **Шаг 4** Пишем конструктор. В модуле '' | + | **Шаг 4.** Пишем конструктор. В модуле '' |
| <code python> | <code python> | ||
| Строка 586: | Строка 649: | ||
| </ | </ | ||
| - | Набор аргументов должен совпадать с набором параметров. | + | Набор аргументов должен совпадать с набором параметров |
| - | **Шаг 5** Пишем метод создания виджета ввода | + | **Шаг 5.** Пишем метод создания виджета ввода |
| <code python> | <code python> | ||
| - | | + | def get_input_widget(self) -> QListWidget: |
| - | if hasattr(self, | + | if hasattr(self, |
| - | return self._widget | + | return self._widget |
| - | | + | |
| - | self._widget.child_widget.setSizePolicy(QSizePolicy(QSizePolicy.Policy.Maximum, | + | self._widget.child_widget.setSizePolicy(QSizePolicy(QSizePolicy.Policy.Maximum, |
| - | self._widget.reset_requested.connect(self.reset_value) | + | self._widget.reset_requested.connect(self.reset_value) |
| - | self._widget.child_widget.itemChanged.connect(self._on_widget_value_changed) | + | |
| - | self._update_widget_params() | + | |
| - | self._update_widget_value() | + | self._update_widget_params() |
| + | self._update_widget_value() | ||
| - | | + | |
| </ | </ | ||
| - | На первом шаге проверяем был ли ранее создан виджет, | + | На первом шаге проверяем был ли ранее создан виджет, |
| - | **Шаг 6** Пишем методы обновления параметров и значения виджета | + | **Шаг 6.** Пишем методы обновления параметров и значения виджета |
| <code python> | <code python> | ||
| - | def _update_widget_value(self) -> None: | + | def _update_widget_value(self) -> None: |
| - | self._widget.child_widget.blockSignals(True) | + | self._widget.child_widget.blockSignals(True) |
| - | for index, value in enumerate(self.items): | + | for index, value in enumerate(self.items): |
| - | item = self._widget.child_widget.item(index) | + | item = self._widget.child_widget.item(index) |
| - | if item: | + | if item: |
| - | if item.text() != utils.get_lang_const_translation(value): | + | if item.text() != utils.get_lang_const_translation(value): |
| - | item.setText(utils.get_lang_const_translation(value)) | + | item.setText(utils.get_lang_const_translation(value)) |
| - | item_check_state = True if item.checkState() == Qt.CheckState.Checked else False | + | item_check_state = True if item.checkState() == Qt.CheckState.Checked else False |
| - | if self.value[index] != item_check_state: | + | if self.value[index] != item_check_state: |
| - | item.setCheckState(Qt.CheckState.Checked if self.value[index] else Qt.CheckState.Unchecked) | + | item.setCheckState(Qt.CheckState.Checked if self.value[index] else Qt.CheckState.Unchecked) |
| - | else: | + | else: |
| - | item = QListWidgetItem(utils.get_lang_const_translation(value)) | + | item = QListWidgetItem(utils.get_lang_const_translation(value)) |
| - | item.setFlags(item.flags() | Qt.ItemIsUserCheckable) | + | item.setFlags(item.flags() | Qt.ItemIsUserCheckable) |
| - | item_state = Qt.CheckState.Checked if self.value[index] else Qt.CheckState.Unchecked | + | item_state = Qt.CheckState.Checked if self.value[index] else Qt.CheckState.Unchecked |
| - | item.setCheckState(item_state) | + | item.setCheckState(item_state) |
| - | self._widget.child_widget.addItem(item) | + | self._widget.child_widget.addItem(item) |
| - | | + | |
| - | for i in range(len(self.items), | + | for i in range(len(self.items), |
| - | self._widget.child_widget.takeItem(i) | + | self._widget.child_widget.takeItem(i) |
| - | self._adjust_widget_height() | + | self._adjust_widget_height() |
| - | self._widget.set_reset_btn_visibility(self._value != self._default_value and self.show_reset_btn) | + | self._widget.set_reset_btn_visibility(self._value != self._default_value and self.show_reset_btn) |
| - | self._widget.child_widget.blockSignals(False) | + | self._widget.child_widget.blockSignals(False) |
| - | def _update_widget_params(self) -> None: | + | |
| - | if hasattr(self, | + | if hasattr(self, |
| - | self._widget.child_widget.setToolTip(utils.get_lang_const_translation(self.tooltip)) | + | self._widget.child_widget.setToolTip(utils.get_lang_const_translation(self.tooltip)) |
| - | self._update_widget_value() | + | self._update_widget_value() |
| </ | </ | ||
| - | В методе '' | + | В методе '' |
| В методе '' | В методе '' | ||
| Строка 646: | Строка 710: | ||
| Используем функцию '' | Используем функцию '' | ||
| - | **Шаг 7** Пишем обработчик события: | + | **Шаг 7.** Пишем обработчик события: |
| <code python> | <code python> | ||
| - | def _on_widget_value_changed(self) -> None: | + | |
| - | self._set_value(tuple(True if (self._widget.child_widget.item(i).checkState() == Qt.CheckState.Checked) else False for i in range(self._widget.child_widget.count()))) | + | self._set_value(tuple(True if (self._widget.child_widget.item(i).checkState() == Qt.CheckState.Checked) else False for i in range(self._widget.child_widget.count()))) |
| - | self._widget.set_reset_btn_visibility(self._value != self._default_value and self.show_reset_btn) | + | self._widget.set_reset_btn_visibility(self._value != self._default_value and self.show_reset_btn) |
| </ | </ | ||
| - | Данный метод вызывается, | + | Данный метод вызывается, |
| Альтернативный способ обновления видимости кнопки сброса; | Альтернативный способ обновления видимости кнопки сброса; | ||
| Строка 666: | Строка 730: | ||
| </ | </ | ||
| - | Метод '' | + | Метод '' |
| + | |||
| + | <code python> | ||
| + | def _on_widget_value_changed(self) -> None: | ||
| + | self._set_value(tuple(True if (self._widget.child_widget.item(i).checkState() == Qt.CheckState.Checked) else False for i in range(self._widget.child_widget.count()))) | ||
| + | self._widget.update_reset_btn_visibility() | ||
| + | </ | ||
| - | **Шаг 8** Пишем метод валидации значения | + | **Шаг 8.** Пишем метод валидации значения |
| <code python> | <code python> | ||
| Строка 691: | Строка 761: | ||
| </ | </ | ||
| - | Примите во внимание, | + | Примите во внимание, |
| - | **Важно!** в процедуре валидации | + | <WRAP center round important 60%> |
| + | В методе | ||
| + | </ | ||
| - | **Шаг 9 (ситуативный)** Иногда нужно переопределить код свойства value, например, | + | **Шаг 9 (ситуативный)** Иногда нужно переопределить код свойства |
| - | ==== 3.4.4 Разработка кастомного интерфейса для контейнера свойств ==== | + | |
| + | ==== 2.4.4 Разработка кастомного интерфейса для контейнера свойств ==== | ||
| Если вас не удовлетворяет стандартный интерфейс вывода виджетов Свойств, | Если вас не удовлетворяет стандартный интерфейс вывода виджетов Свойств, | ||
| Строка 759: | Строка 832: | ||
| Тут все просто, | Тут все просто, | ||
| - | ==== 3.5 Несколько слов о недостатках ==== | + | ==== 2.5 Несколько слов о недостатках ==== |
| * При импорте плагины выполняются не в изолированной среде, а фактически становятся частью всей программы и каждому из них доступен весь код в рамках сессии. Таким образом любой плагин может вмешаться в работу Менеджера и других плагинов, | * При импорте плагины выполняются не в изолированной среде, а фактически становятся частью всей программы и каждому из них доступен весь код в рамках сессии. Таким образом любой плагин может вмешаться в работу Менеджера и других плагинов, | ||
| Строка 767: | Строка 840: | ||
| Проект будет развиваться, | Проект будет развиваться, | ||
| + | |||
| + | {{section> | ||
products/pyrog/tutorials/dev/main.1780610049.txt.gz · Последнее изменение: — ironmesh