Создание пользовательских виджетов для 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() |
Заголовочный файл, который необходимо включить в приложениях, использующих этот виджет. Эта информация хранится в файлах UI и будет использоваться uic для создания соответствующего #includes утверждения в генерируемом коде для формы, содержащей пользовательский виджет. |
icon() |
Иконка, которая может быть использована для представления виджета в поле виджетов Qt Designer. |
isContainer() |
Истина, если виджет будет использоваться для размещения дочерних виджетов; ложь в противном случае. |
createWidget() |
Указатель QWidget на экземпляр пользовательского виджета, созданного с предоставленным родителем. Примечание: createWidget() — это функция-фабрика, отвечающая только за создание виджета. Свойства пользовательского виджета не будут доступны до тех пор, пока load() не вернет результат. |
domXml() |
Описание свойств виджета, таких как имя объекта, размер подсказки и другие стандартные свойства QWidget. |
codeTemplate() |
Эта функция зарезервирована для будущего использования Qt Designer. |
Можно также переопределить две другие виртуальные функции:
initialize() |
Настройка расширений и других функций для пользовательских виджетов. Пользовательские расширения контейнеров (см. QDesignerContainerExtension) и расширения меню задач (см. QDesignerTaskMenuExtension) должны быть настроены в этой функции. |
isInitialized() |
Возвращает истину, если виджет был инициализирован; возвращает ложь в противном случае. Переопределения обычно проверяют, была ли вызвана функция initialize(), и возвращают результат этой проверки. |
Примечания по функции domXml()
Функция domXml() возвращает фрагмент файла UI, используемый фабрикой виджетов Qt Designer для создания пользовательского виджета и его соответствующих свойств.
С Qt 4.4 поле виджетов Qt Designer позволяет использовать полный файл UI для описания одного пользовательского виджета. Файл UI можно загрузить с помощью тега <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() плагина.
Сборка и установка плагина
Простой плагин
Пример плагина пользовательского виджета Custom Widget Plugin Example демонстрирует простой плагин 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, они не будут загружены и установлены. Более подробную информацию о плагинах см. в документе Plugins 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/archives/qt-5.6/designer-creating-custom-widgets.html