Создание пользовательских виджетов для Qt Designer
Плагин-ориентированная архитектура Qt Designer позволяет редактировать пользовательские и сторонние виджеты так же, как и стандартные виджеты Qt. Все функции пользовательского виджета доступны в Qt Designer, включая свойства виджета, сигналы и слоты. Так как Qt Designer использует реальные виджеты во время процесса разработки формы, пользовательские виджеты будут отображаться так же, как и при предварительном просмотре.
Модуль QtDesigner предоставляет возможность создавать пользовательские виджеты в Qt Designer.
Начало работы
Для интеграции пользовательского виджета с Qt Designer требуется соответствующее описание виджета и соответствующий файл .pro.
Предоставление описания интерфейса
Чтобы сообщить Qt Designer о типе виджета, который вы хотите предоставить, создайте подкласс QDesignerCustomWidgetInterface, описывающий различные свойства вашего виджета. Большинство из них предоставляются функциями, которые являются чисто виртуальными в базовом классе, потому что только автор плагина может предоставить эту информацию.
| Функция | Описание возвращаемого значения |
|---|---|
name() |
Название класса, предоставляющего виджет. |
group() |
Группа в поле виджетов Qt Designer, к которой принадлежит виджет. |
toolTip() |
Краткое описание, чтобы пользователи могли идентифицировать виджет в Qt Designer. |
whatsThis() |
Более подробное описание виджета для пользователей Qt Designer. |
includeFile() |
Заголовочный файл, который должен быть включён в приложениях, использующих этот виджет. Эта информация хранится в файлах пользовательского интерфейса и будет использоваться uic для создания соответствующего #includes оператора в коде, генерируемом для формы, содержащей пользовательский виджет. |
icon() |
Иконка, которая может использоваться для представления виджета в поле виджетов Qt Designer. |
isContainer() |
True, если виджет будет использоваться для хранения дочерних виджетов; в противном случае false. |
createWidget() |
Указатель на объект QWidget экземпляра пользовательского виджета, созданного с предоставленным родителем. Примечание: createWidget() — это функция-фабрика, ответственная только за создание виджета. Свойства пользовательского виджета станут доступны только после возврата load(). |
domXml() |
Описание свойств виджета, таких как имя объекта, размер подсказки и другие стандартные свойства QWidget. |
codeTemplate() |
Эта функция предназначена для будущего использования Qt Designer. |
Можно также переопределить две другие виртуальные функции:
initialize() |
Настройка расширений и других функций для пользовательских виджетов. Расширения пользовательских контейнеров (см. QDesignerContainerExtension) и расширения меню задач (см. QDesignerTaskMenuExtension) должны быть настроены в этой функции. |
isInitialized() |
Возвращает true, если виджет был инициализирован; в противном случае возвращает false. Переопределения обычно проверяют, была ли вызвана функция initialize(), и возвращают результат этой проверки. |
Замечания по функции domXml()
Функция domXml() возвращает фрагмент файла пользовательского интерфейса, который используется фабрикой виджетов Qt Designer для создания пользовательского виджета и его соответствующих свойств.
Начиная с Qt 4.4, поле виджетов Qt Designer позволяет использовать целый файл пользовательского интерфейса для описания одного пользовательского виджета. Файл пользовательского интерфейса может быть загружен с помощью тега <ui>. Указание тега <ui> позволяет добавить элемент <customwidget>, который содержит дополнительную информацию для пользовательских виджетов. Тег <widget> достаточно, если дополнительная информация не требуется.
Если пользовательский виджет не предоставляет разумной подсказки размера, необходимо указать стандартную геометрию в строке, возвращаемой функцией domXml() в вашем подклассе. Например, пример AnalogClockPlugin, предоставленный примером плагина пользовательского виджета, определяет стандартную геометрию виджета следующим образом:
...
" <property name=\"geometry\">\n"
" <rect>\n"
" <x>0</x>\n"
" <y>0</y>\n"
" <width>100</width>\n"
" <height>100</height>\n"
" </rect>\n"
" </property>\n"
... Дополнительная функция функции domXml() заключается в том, что если она возвращает пустую строку, виджет не будет установлен в поле виджетов Qt Designer. Однако он по-прежнему может использоваться другими виджетами в форме. Эта функция используется для скрытия виджетов, которые не должны быть явно созданы пользователем, но необходимы другим виджетам.
Полное описание пользовательского виджета выглядит так:
<ui language="c++"> displayname="MyWidget">
<widget class="widgets::MyWidget" name="mywidget"/>
<customwidgets>
<customwidget>
<class>widgets::MyWidget</class>
<addpagemethod>addPage</addpagemethod>
<propertyspecifications>
<stringpropertyspecification name="fileName" notr="true" type="singleline"/>
<stringpropertyspecification name="text" type="richtext"/>
<tooltip name="text">Explanatory text to be shown in Property Editor</tooltip>
</propertyspecifications>
</customwidget>
</customwidgets>
</ui> Атрибуты тега <ui>:
| Атрибут | Наличие | Значения | Комментарий |
|---|---|---|---|
language |
необязательно | "c++", "jambi" | Этот атрибут указывает язык, для которого предназначен пользовательский виджет. Он в основном служит для предотвращения появления C++-плагинов в Qt Jambi. |
displayname |
необязательно | Имя класса | Значение атрибута отображается в поле «Виджет» и может использоваться для удаления имен пространств имён. |
Тег <addpagemethod> сообщает Qt Designer и uic, какой метод следует использовать для добавления страниц в контейнерный виджет. Это относится к контейнерным виджетам, которые требуют вызова определённого метода для добавления дочернего элемента, а не добавления дочернего элемента путём передачи родительского элемента. В частности, это актуально для контейнеров, которые не являются подклассом контейнеров, предоставляемых в Qt Designer, но основаны на понятии «Текущая страница». Кроме того, вам необходимо предоставить для них расширение контейнера.
Элемент <propertyspecifications> может содержать список метаданных свойств.
Тег <tooltip> может использоваться для указания всплывающей подсказки, которая будет отображаться в редакторе свойств при наведении курсора на свойство. Имя свойства задаётся в атрибуте name, а текст элемента — это подсказка. Эта функция была добавлена в Qt 5.6.
Для свойств типа строка можно использовать тег <stringpropertyspecification>. Этот тег имеет следующие атрибуты:
| Атрибут | Наличие | Значения | Комментарий |
|---|---|---|---|
name |
обязательно | Имя свойства | |
type |
обязательно | См. таблицу ниже | Значение атрибута определяет, как редактор свойств будет обрабатывать их. |
notr |
необязательно | "true", "false" | Если атрибут равен "true", значение не предназначено для перевода. |
Значения атрибута type свойства типа строка:
| Значение | Тип |
|---|---|
"richtext" |
Форматированный текст. |
"multiline" |
Многострочный простой текст. |
"singleline" |
Однострочный простой текст. |
"stylesheet" |
Таблица стилей CSS. |
"objectname" |
Имя объекта (ограниченный набор допустимых символов). |
"url" |
URL, имя файла. |
Требования к плагинам
Для правильной работы плагинов на всех платформах необходимо убедиться, что они экспортируют символы, необходимые Qt Designer.
Прежде всего, класс плагина должен быть экспортирован, чтобы плагин мог быть загружен Qt Designer. Используйте макрос Q_PLUGIN_METADATA() для этого. Также должен использоваться макрос QDESIGNER_WIDGET_EXPORT для определения каждого класса пользовательского виджета внутри плагина, который будет инстанцирован Qt Designer.
Создание корректных виджетов
Некоторые пользовательские виджеты имеют особые функции пользовательского интерфейса, которые могут делать их поведение отличным от поведения многих стандартных виджетов в Qt Designer. В частности, если пользовательский виджет захватывает клавиатуру в результате вызова QWidget::grabKeyboard(), это повлияет на работу Qt Designer.
Чтобы предоставить пользовательским виджетам специальное поведение в Qt Designer, реализуйте функцию initialize(), чтобы настроить процесс создания виджета для поведения, специфичного для Qt Designer. Эта функция будет вызвана в первый раз до любого вызова createWidget() и, возможно, установит внутренний флаг, который можно будет проверить позднее, когда Qt Designer вызовет функцию createWidget() плагина.
Сборка и установка плагина
Простой плагин
Пример Плагина пользовательского виджета демонстрирует простой плагин Qt Designer.
Файл .pro для плагина должен указывать заголовки и исходные файлы как для пользовательского виджета, так и для интерфейса плагина. Как правило, этот файл должен только указать, что проект плагина должен быть построен как библиотека, но с определённой поддержкой плагина для Qt Designer. Это делается с помощью следующих объявлений:
QT += widgets uiplugin CONFIG += plugin TEMPLATE = lib
Переменная QT содержит ключевое слово uiplugin. Это указывает, что плагин использует только абстрактные интерфейсы QDesignerCustomWidgetInterface и QDesignerCustomWidgetCollectionInterface и не имеет связи с библиотеками Qt Designer. При обращении к другим интерфейсам Qt Designer, имеющим связь, следует использовать designer; это гарантирует, что плагин динамически связывается с библиотеками Qt Designer и имеет временную зависимость от них.
Если плагины созданы в режиме, несовместимом с Qt Designer, они не будут загружены и установлены. Для получения дополнительной информации о плагинах см. документ Плагины HOWTO.
Также необходимо убедиться, что плагин установлен вместе с другими плагинами виджетов Qt Designer:
target.path = $$[QT_INSTALL_PLUGINS]/designer INSTALLS += target
Переменная $[QT_INSTALL_PLUGINS] является плейсхолдером для местоположения установленных плагинов Qt. Вы можете настроить Qt Designer на поиск плагинов в других местоположениях, задав переменную окружения QT_PLUGIN_PATH перед запуском приложения.
Примечание: Qt Designer будет искать подкаталог designer в каждом предоставленном пути.
См. QCoreApplication::libraryPaths() для получения дополнительной информации о настройке путей для библиотек и плагинов с приложениями Qt.
Разделение плагина
В реальном сценарии вам не нужно, чтобы приложение, использующее пользовательские виджеты, зависело от заголовков и библиотек Qt Designer, как показано в простом подходе, описанном выше.
Следующие разделы описывают, как это исправить.
Связывание виджета с приложением
Исходный и заголовочный файлы пользовательского виджета можно общих между приложением и Qt Designer, создав файл .pri для включения:
INCLUDEPATH += $$PWD HEADERS += $$PWD/analogclock.h SOURCES += $$PWD/analogclock.cpp
Затем этот файл будет включен в файл .pro плагина и приложения:
include(customwidget.pri)
Использование виджета с помощью библиотеки
Другой подход заключается в размещении виджета в библиотеке, которая связана как с плагином Qt Designer, так и с приложением. Рекомендуется использовать статические библиотеки, чтобы избежать проблем с поиском библиотеки во время выполнения.
Для динамических библиотек см. Создание динамических библиотек.
Использование плагина с QUiLoader
Предпочтительный способ добавления пользовательских виджетов в QUiLoader заключается в наследовании от него и переопределении QUiLoader::createWidget().
Однако также можно использовать пользовательские плагины виджетов Qt Designer (см. QUiLoader::pluginPaths() и связанные функции). Чтобы избежать необходимости развертывания библиотек Qt Designer на целевом устройстве, эти плагины не должны быть связаны с библиотеками Qt Designer (QT = uiplugin, см. Создание пользовательских виджетов для Qt Designer#BuildingandInstallingthePlugin).
Связанные примеры
Для получения дополнительной информации об использовании пользовательских виджетов в Qt Designer см. примеры Плагин пользовательского виджета и Плагин мирового времени для получения дополнительной информации об использовании пользовательских виджетов в Qt Designer. Также вы можете использовать класс QDesignerCustomWidgetCollectionInterface для объединения нескольких пользовательских виджетов в одну библиотеку.
© The Qt Company Ltd
Licensed under the GNU Free Documentation License, Version 1.3.
https://doc.qt.io/qt-5.14/designer-creating-custom-widgets.html