自定义小部件插件
为Qt Widgets Designer 创建自定义 Widget 插件。
本例中使用的自定义 Widget 基于模拟时钟示例,不提供任何自定义信号或插槽。
准备工作
要提供可与Qt Widgets Designer 一起使用的自定义 widget,我们需要提供一个独立的实现并提供一个插件接口。在本示例中,为了方便起见,我们重复使用了模拟时钟示例。
项目文件
CMake
项目文件需要说明要构建一个链接到Qt Widgets Designer 库的插件:
find_package(Qt6 REQUIRED COMPONENTS Core Gui UiPlugin Widgets) qt_add_plugin(customwidgetplugin) target_link_libraries(customwidgetplugin PUBLIC Qt::Core Qt::Gui Qt::UiPlugin Qt::Widgets )
链接库列表指定Qt::UiPlugin
。这表明插件只使用QDesignerCustomWidgetInterface 和QDesignerCustomWidgetCollectionInterface 的抽象接口,而与Qt Widgets Designer 库没有链接。访问Qt Widgets Designer 的其他有链接的接口时,应使用Designer
代替;这样可确保插件动态链接到Qt Widgets Designer 库,并在运行时依赖于这些库。
下面的示例展示了如何添加 widget 的头文件和源文件:
target_sources(customwidgetplugin PRIVATE analogclock.cpp analogclock.h customwidgetplugin.cpp customwidgetplugin.h )
我们提供了插件接口的实现,以便Qt Widgets Designer 可以使用自定义 widget。
同样重要的是,要确保插件安装在Qt Widgets Designer 可以搜索到的位置。为此,我们为项目指定了目标路径,并将其添加到安装项目列表中:
set(INSTALL_EXAMPLEDIR "${QT6_INSTALL_PREFIX}/${QT6_INSTALL_PLUGINS}/designer") install(TARGETS customwidgetplugin RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}" BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}" LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}" )
自定义 widget 是作为库创建的。在安装项目(使用ninja install
或类似的安装程序)时,它将与其他Qt Widgets Designer 插件一起安装。
有关插件的更多信息,请参阅如何创建 Qt 插件文档。
qmake
下面的示例展示了如何将插件链接到Qt Widgets Designer 库:
CONFIG += plugin TEMPLATE = lib QT += widgets uiplugin
QT
变量包含关键字uiplugin
,相当于Qt::UiPlugin
库。
下面的示例展示了如何添加 widget 的头文件和源文件:
HEADERS = analogclock.h \ customwidgetplugin.h SOURCES = analogclock.cpp \ customwidgetplugin.cpp OTHER_FILES += analogclock.json
下面的示例展示了如何将插件安装到Qt Widgets Designer 的插件路径:
TARGET = $$qtLibraryTarget($$TARGET) target.path = $$[QT_INSTALL_PLUGINS]/designer INSTALLS += target
模拟时钟类的定义和实现
AnalogClock
类的定义和实现方式与模拟时钟示例中描述的完全相同。由于该类自成一体,不需要任何外部配置,因此无需修改即可作为Qt Widgets Designer 中的自定义 widget 使用。
模拟时钟插件类定义
AnalogClock
类通过AnalogClockPlugin
类向Qt Widgets Designer 暴露。该类继承自QObject 和QDesignerCustomWidgetInterface 类,并实现了QDesignerCustomWidgetInterface 定义的接口。
为确保 Qt 将 Widget 识别为插件,请通过添加Q_PLUGIN_METADATA()
宏导出 Widget 的相关信息:
class AnalogClockPlugin : public QObject, public QDesignerCustomWidgetInterface { Q_OBJECT Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QDesignerCustomWidgetInterface") Q_INTERFACES(QDesignerCustomWidgetInterface) public: explicit AnalogClockPlugin(QObject *parent = nullptr); bool isContainer() const override; bool isInitialized() const override; QIcon icon() const override; QString domXml() const override; QString group() const override; QString includeFile() const override; QString name() const override; QString toolTip() const override; QString whatsThis() const override; QWidget *createWidget(QWidget *parent) override; void initialize(QDesignerFormEditorInterface *core) override; private: bool initialized = false; };
这些函数提供了有关 widget 的信息,Qt Widgets Designer 可以在widget 框中使用这些信息。initialized
私有成员变量用于记录插件是否已被Qt Widgets Designer 初始化。
请注意,类定义中唯一与该特定自定义 widget 相关的部分是类名。
模拟时钟插件的实现
该类的构造函数只需调用QObject 基类构造函数,并将initialized
变量设置为false
。
Qt Widgets Designer 当需要时,将通过调用 函数初始化插件:initialize()
void AnalogClockPlugin::initialize(QDesignerFormEditorInterface * /* core */) { if (initialized) return; initialized = true; }
在此示例中,将测试initialized
私有变量,只有在插件尚未初始化时才将其设置为true
。虽然该插件在初始化时不需要执行任何特殊代码,但我们可以在初始化测试后加入此类代码。
isInitialized()
函数可让Qt Widgets Designer 知道插件是否已准备就绪可以使用:
bool AnalogClockPlugin::isInitialized() const { return initialized; }
自定义部件的实例由createWidget()
函数提供。模拟时钟的实现非常简单:
在这种情况下,自定义部件只需要指定parent
。如果需要为部件提供其他参数,可在此处引入。
以下函数为Qt Widgets Designer 提供信息,用于在 widget 框中表示 widget。name()
函数返回提供自定义 widget 的类的名称:
QString AnalogClockPlugin::name() const { return u"AnalogClock"_s; }
group()
函数用于描述自定义 widget 所属的 widget 类型:
QString AnalogClockPlugin::group() const { return u"Display Widgets [Examples]"_s; }
widget 插件将放置在Qt Widgets Designer 的 widget 框中由其组名称标识的部分。小部件框中用于表示小部件的图标由icon()
函数返回:
QIcon AnalogClockPlugin::icon() const { return {}; }
在这种情况下,我们会返回一个空图标,以表示我们没有可用来表示 widget 的图标。
可以为 widget 框中的自定义 widget 条目提供工具提示和 "这是什么?toolTip()
函数应返回一条描述该 widget 的简短信息:
QString AnalogClockPlugin::toolTip() const { return {}; }
whatsThis()
函数可以返回较长的描述:
QString AnalogClockPlugin::whatsThis() const { return {}; }
isContainer()
函数会告诉Qt Widgets Designer 该 widget 是否应该用作其他 widget 的容器。如果不是,Qt Widgets Designer 将不允许用户在其中放置 widget。
bool AnalogClockPlugin::isContainer() const { return false; }
Qt XML 中的大多数 widget 都可以包含子 widget,但只有在Qt Widgets Designer 中为此目的使用专用容器 widget 才有意义。通过返回false
,我们表明自定义 widget 不能容纳其他 widget;如果返回 true,Qt Widgets Designer 将允许在模拟时钟内部放置其他 widget 并定义布局。
domXml()
函数提供了一种方法,可将 Widget 的默认设置包含在Qt Widgets Designer 使用的标准 XML 格式中。在这种情况下,我们只需指定部件的几何尺寸:
QString AnalogClockPlugin::domXml() const { return uR"( <ui language="c++"> <widget class="AnalogClock" name="analogClock"> )" R"( <property name="geometry"> <rect> <x>0</x> <y>0</y> <width>100</width> <height>100</height> </rect> </property> ") R"( <property name="toolTip"> <string>The current time</string> </property> <property name="whatsThis"> <string>The analog clock widget displays the current time.</string> </property> </widget> </ui> )"_s; }
如果 widget 提供了合理的尺寸提示,则无需在此定义。此外,返回空字符串而不是<widget>
元素将告诉Qt Widgets Designer 不要将 widget 安装到 widget 框中。
为了让应用程序可以使用模拟时钟部件,我们实现了includeFile()
函数,以返回包含自定义部件类定义的头文件的名称:
QString AnalogClockPlugin::includeFile() const { return u"analogclock.h"_s; }
© 2025 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.