为...创建自定义小部件Qt Widgets Designer
Qt Widgets Designer的基于插件的架构允许用户像编辑标准 Qt Widgets 一样,编辑用户自定义和第三方自定义控件。 所有自定义控件的功能(包括控件属性、信号和槽)均可供Qt Widgets Designer 使用。由于Qt Widgets Designer 在表单设计过程中使用的是真实的控件,因此自定义控件在预览时的显示效果与实际一致。
QtDesigner 模块使您能够在Qt Widgets Designer 中创建自定义控件。
入门指南
要将自定义小部件集成到Qt Widgets Designer 中,您需要为该小部件准备一份合适的描述以及相应的项目文件。
提供接口描述
为了向Qt Widgets Designer 说明您要提供的控件类型,请创建QDesignerCustomWidgetInterface 的子类,用于描述该控件暴露的各项属性。其中大部分属性由基类中的纯虚函数提供,因为只有插件的作者才能提供这些信息。
| 函数 | 返回值的说明 |
|---|---|
name() | 提供该小部件的类名。 |
group() | 该小部件在Qt Widgets Designer 小部件框中所属的组。 |
toolTip() | 用于帮助用户在Qt Widgets Designer 中识别该小部件的简短描述。 |
whatsThis() | 面向Qt Widgets Designer 用户的控件详细说明。 |
includeFile() | 在使用此控件的应用程序中必须包含的头文件。此信息存储在 UI 文件中,uic 将利用它,在为包含自定义控件的表单生成的代码中创建合适的#includes 语句。 |
icon() | 可在Qt Widgets Designer 的控件框中用于代表该控件的图标。 |
isContainer() | 如果该控件将用于容纳子控件,则为 true;否则为 false。 |
createWidget() | 指向自定义小部件实例的QWidget 指针,该实例使用提供的父级构建而成。 注意:createWidget () 是一个工厂函数,仅负责创建小部件。在 load() 返回之前,自定义小部件的属性将不可用。 |
domXml() | 小部件属性的描述,例如其对象名称、尺寸提示以及其他标准的QWidget 属性。 |
codeTemplate() | 此函数预留供Qt Widgets Designer 未来使用。 |
还有两个虚拟函数也可以重新实现:
initialize() | 用于为自定义控件设置扩展和其他功能。自定义容器扩展(参见QDesignerContainerExtension )和任务菜单扩展(参见QDesignerTaskMenuExtension )应在此函数中进行设置。 |
isInitialized() | 如果小部件已初始化,则返回 true;否则返回 false。重写时通常会检查是否已调用initialize() 函数,并返回该检查的结果。 |
关于domXml() 函数的说明
domXml() 函数返回一个 UI 文件片段,该片段将由Qt Widgets Designer 的控件工厂用于创建自定义控件及其相关属性。
自 Qt 4.4 起,Qt Widgets Designer 的控件框允许使用完整的 UI 文件来描述一个自定义控件。该 UI 文件可通过<ui> 标签加载。指定 <UI> 标签后,即可添加 <CUSTOMWIDGET> 元素,其中包含自定义控件的附加信息。若无需附加信息,仅使用<widget> 标签即可
如果自定义控件未提供合理的尺寸提示,则必须在子类的domXml() 函数返回的字符串中指定默认几何属性。例如,自定义控件插件示例中提供的AnalogClockPlugin 文件,通过以下方式定义了默认控件几何属性:
...
R"(
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>100</width>
<height>100</height>
</rect>
</property>
")
...domXml() 函数的另一项特性是:如果它返回空字符串,该控件将不会被安装到Qt Widgets 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 Widgets Designer 和uic应使用哪种方法向容器控件添加页面。这适用于那些需要通过调用特定方法来添加子元素,而非通过传递父元素来添加子元素的容器控件。 特别是,这适用于那些并非Qt Widgets Designer 中提供的容器的子类,但基于“当前页面”(Current Page)概念的容器。此外,您需要为它们提供一个容器扩展。
<propertyspecifications> 元素可以包含一组属性元数据。
<tooltip> 标签可用于指定在鼠标悬停于属性上时,属性编辑器中显示的工具提示。属性名称通过name 属性指定,而元素文本即为工具提示。此功能于 Qt 5.6 中新增。
对于字符串类型的属性,可以使用<stringpropertyspecification> 标签。该标签具有以下属性:
| 属性 | 是否存在 | 取值 | 说明 |
|---|---|---|---|
name | 必填 | 属性名称 | |
type | 必填 | 参见下表 | 该属性的值决定了属性编辑器将如何处理它们。 |
notr | 可选 | “true”、“false” | 如果该属性为“true”,则该值不应被翻译。 |
字符串属性的type 属性的取值:
| 值 | 类型 |
|---|---|
"richtext" | 富文本。 |
"multiline" | 多行纯文本。 |
"singleline" | 单行纯文本。 |
"stylesheet" | CSS 样式表。 |
"objectname" | 对象名称(有效字符集受限)。 |
"url" | URL、文件名。 |
插件要求
为了使插件在所有平台上都能正常工作,您需要确保它们导出了Qt Widgets Designer 所需的符号。
首先,必须导出插件类,以便Qt Widgets Designer 能够加载该插件。请使用Q_PLUGIN_METADATA()宏来实现这一点。此外,必须使用QDESIGNER_WIDGET_EXPORT 宏来定义插件中的每个自定义控件类,Qt Widgets Designer 将实例化这些类。
创建行为规范的小部件
某些自定义小部件具有特殊的用户界面功能,这可能会导致它们的行为与Qt Widgets Designer 中许多标准小部件不同。具体来说,如果自定义小部件因调用QWidget::grabKeyboard()而占用键盘,则Qt Widgets Designer 的操作将受到影响。
若要在Qt Widgets Designer 中赋予自定义控件特殊行为,请提供 initialize() 函数的实现,以配置控件的构建过程,使其具备Qt Widgets Designer 特有的行为。该函数将在首次调用 createWidget() 之前被调用,此时可以设置一个内部标志,以便在Qt Widgets Designer 调用插件的 createWidget() 函数时进行检测。
构建和安装插件
一个简单的插件
“自定义小部件插件”演示了一个简单的Qt Widgets Designer 插件。
插件的项目文件必须指定自定义控件和插件接口的头文件及源文件。通常,该文件只需指定插件项目将作为库进行构建,但需包含针对Qt Widgets Designer 的特定插件支持。对于CMake ,可通过以下声明实现:
find_package(Qt6 REQUIRED COMPONENTS Core Gui UiPlugin Widgets)
qt_add_plugin(customwidgetplugin)
target_sources(customwidgetplugin PRIVATE
analogclock.cpp analogclock.h
customwidgetplugin.cpp customwidgetplugin.h
)
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 库,并对其具有运行时依赖关系。
此外,还必须确保该插件与其他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}"
)对于qmake :
CONFIG += plugin
TEMPLATE = lib
HEADERS = analogclock.h \
customwidgetplugin.h
SOURCES = analogclock.cpp \
customwidgetplugin.cpp
OTHER_FILES += analogclock.jsonQT 变量包含关键字uiplugin ,它等同于Qt::UiPlugin 库。
此外,还需确保该插件与其他Qt Widgets Designer 控件插件一同安装:
target.path = $$[QT_INSTALL_PLUGINS]/designer
INSTALLS += target$[QT_INSTALL_PLUGINS] 变量是已安装Qt插件位置的占位符。您可以在运行应用程序之前设置QT_PLUGIN_PATH 环境变量,从而配置Qt Widgets Designer 在其他位置查找插件。
注意: Qt Widgets Designer 会在提供的每个路径中查找名为designer 的子目录。
有关在 Qt 应用程序中自定义库和插件路径的更多信息,请参阅QCoreApplication::libraryPaths()。
如果插件是在与Qt Widgets Designer 不兼容的模式下构建的,则不会被加载和安装。有关插件的更多信息,请参阅《插件使用指南》(Plugins HOWTO)文档。
拆分插件
上文所述的简单方法在使用Qt Widgets Designer 中其他具有链接关系的接口时会引发一个问题:使用自定义控件的应用程序将依赖于Qt Widgets Designer 的头文件和库文件。在实际应用中,这种情况是不希望看到的。
以下各节将介绍如何解决此问题。
将控件链接到应用程序中
在使用qmake 时,可以通过创建.pri 文件并将其包含进来,使应用程序和Qt Widgets Designer 之间能够共享自定义控件的源文件和头文件:
INCLUDEPATH += $$PWD
HEADERS += $$PWD/analogclock.h
SOURCES += $$PWD/analogclock.cpp随后,该文件将被插件和应用程序的.pro 文件所包含:
include(customwidget.pri)使用CMake 时,小部件的源文件也可以以类似的方式添加到应用程序项目中。
使用库共享小部件
另一种方法是将控件放入一个库中,该库既与Qt Widgets Designer 插件链接,也与应用程序链接。建议使用静态库,以避免运行时定位库的问题。
关于共享库,请参阅《创建共享库》。
在 QUiLoader 中使用该插件
向QUiLoader 添加自定义控件的首选方法是继承该类,并重写QUiLoader::createWidget()方法。
不过,也可以使用Qt Widgets Designer 自定义小部件插件(参见QUiLoader::pluginPaths() 及其相关函数)。为了避免将Qt Widgets Designer 库部署到目标设备上,这些插件不应与Qt Widgets Designer 库存在任何关联(QT = uiplugin ,参见《Qt Widgets Designer 自定义小部件创建指南》中的“#构建和安装插件”部分)。
相关示例
有关在Qt Widgets Designer 中使用自定义小部件的更多信息,请参阅“自定义小部件插件”和“任务菜单扩展”示例;有关在Qt Widgets Designer 中使用自定义小部件的更多信息,请参阅相关示例。此外,您可以使用QDesignerCustomWidgetCollectionInterface 类将多个自定义小部件合并为一个库。
© 2026 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.