使用 C++ 编写 QML 扩展
关于使用 Qt C++ 扩展 QML 的教程。
Qt QML 模块提供了一套 API,用于通过 C++ 扩展 QML。你可以编写扩展来添加你自己的 QML 类型,扩展现有的 Qt 类型,或调用普通 QML 代码无法访问的 C/C++ 函数。
本教程展示了如何使用 C++ 编写 QML 扩展,其中包括 QML 核心功能,包括属性、信号和绑定。它还展示了如何通过插件来部署扩展。
本教程中所涉及的许多主题在 概述——QML 和 C++ 集成 及其文档子主题中有更详细的说明。特别是,您可能对 向 QML 公开 C++ 类型的属性 和 在 C++ 中定义 QML 类型 这两个子主题感兴趣。
运行教程示例
本教程中的代码都可通过 Examples 获取,包含每个章节相关的子项目。在 Qt Creator 中,打开 欢迎 模式并从 示例 中选择 extending-qml。

创建教程项目
我们按照 Qt Creator: 创建 Qt Quick 项目 中的说明,使用 Qt Creator 中的 Qt Quick Application 模板创建一个新项目。
第 1 章:创建新类型
在扩展 QML 时,一个常见的任务是提供一个新的 QML 类型,支持一些超出内置 Qt Quick 类型所提供的自定义功能。例如,这可能是为了实现特定的数据模型,或提供具有自定义绘画和绘图功能的类型,或访问系统功能(如网络编程,不能通过内置的 QML 功能访问)。
在本教程中,我们将展示如何使用 Qt Quick 模块中的 C++ 类来扩展 QML。最终结果将是显示一个简单的饼图,由几个自定义 QML 类型实现,这些类型通过 QML 功能(如绑定和信号)连接在一起,并通过插件提供给 QML 运行时。
首先,让我们创建一个新的 QML 类型,叫做 “PieChart”,它有两个属性:名称和颜色。我们将使其在名为 “Charts” 的可导入类型命名空间中可用,版本为 1.0。
我们希望 PieChart 类型可以这样在 QML 中使用:
import Charts 1.0 PieChart { width: 100; height: 100 name: "A simple pie chart" color: "red" }
要做到这点,我们需要一个 C++ 类来封装 PieChart 类型和它的两个属性。由于 QML 广泛使用 Qt 的 元对象系统,这个新类必须:
- 继承自 QObject
- 使用 Q_PROPERTY 宏来声明其属性
类的声明
下面是我们的 PieChart 类,定义在 piechart.h 中:
#include <QtQuick/QQuickPaintedItem> #include <QColor> class PieChart : public QQuickPaintedItem { Q_OBJECT Q_PROPERTY(QString name READ name WRITE setName) Q_PROPERTY(QColor color READ color WRITE setColor) QML_ELEMENT public: PieChart(QQuickItem *parent = nullptr); QString name() const; void setName(const QString &name); QColor color() const; void setColor(const QColor &color); void paint(QPainter *painter) override; private: QString m_name; QColor m_color; };
该类继承自 QQuickPaintedItem,因为我们要重写 QQuickPaintedItem::paint(),以便用 QPainter API 进行绘图操作。如果这个类只是表示一些数据类型,而不是实际需要显示的项目,它可以简单地继承QObject。或者,如果我们想扩展现有的基于 QObject 的类的功能,它可以从该类继承。另外,如果我们想创建一个不需要用 QPainter API 进行绘图操作的可视项,我们可以只继承 QQuickItem。
PieChart 类用 Q_PROPERTY 定义了 名称 和 颜色 这两个属性,并重写了 QQuickPaintedItem::paint()。PieChart 类是用 QML_ELEMENT 宏注册的,以允许它被 QML 使用。如果你不注册这个类,app.qml 将无法创建 PieChart。
qmake 设置
为了使注册生效,在项目文件的 CONFIG 中添加了 qmltypes 选项,并设置了 QML_IMPORT_NAME 和 QML_IMPORT_MAJOR_VERSION:
CONFIG += qmltypes QML_IMPORT_NAME = Charts QML_IMPORT_MAJOR_VERSION = 1
CMake 设置
同样,要在使用 CMake 时使注册生效,请使用 qt_add_qml_module 命令:
qt_add_qml_module(chapter1-basics
URI Charts
VERSION 1.0
QML_FILES app.qml
NO_RESOURCE_TARGET_PATH
)
类的实现
piechart.cpp 中的类实现只是简单地设置和返回 m_name 和 m_color 值,并实现 paint() 来绘制一个简单的饼图:
PieChart::PieChart(QQuickItem *parent) : QQuickPaintedItem(parent) { } ... void PieChart::paint(QPainter *painter) { QPen pen(m_color, 2); painter->setPen(pen); painter->setRenderHints(QPainter::Antialiasing, true); painter->drawPie(boundingRect().adjusted(1, 1, -1, -1), 90 * 16, 290 * 16); }
QML 用法
现在我们已经定义了 PieChart 类型,我们将在 QML 中使用它。app.qml 创建了一个 PieChart item,并使用一个标准的 QML Text 显示饼图的文本信息。
import Charts import QtQuick Item { width: 300; height: 200 PieChart { id: aPieChart anchors.centerIn: parent width: 100; height: 100 name: "A simple pie chart" color: "red" } Text { anchors { bottom: parent.bottom; horizontalCenter: parent.horizontalCenter; bottomMargin: 20 } text: aPieChart.name } }
请注意,尽管颜色在 QML 中被指定为字符串,但对于 PieChart 的 color 属性,它被自动转换为一个 QColor 对象。各种 值类型 都会自动转换。例如,像 “640x480” 这样的字符串可以自动转换为 QSize 值。
我们还将创建一个 C++ 应用程序,使用 QQuickView 来运行和显示 app.qml。
这是应用程序 main.cpp:
#include "piechart.h" #include <QtQuick/QQuickView> #include <QGuiApplication> int main(int argc, char *argv[]) { QGuiApplication app(argc, argv); QQuickView view; view.setResizeMode(QQuickView::SizeRootObjectToView); view.setSource(QUrl("qrc:///app.qml")); view.show(); return QGuiApplication::exec(); }
项目构建
为了构建项目,我们包含文件,链接库,并为公开给 QML 的类型定义了一个名为 “Charts” 的类型命名空间,版本为 1.0。
使用 qmake:
QT += qml quick
CONFIG += qmltypes
QML_IMPORT_NAME = Charts
QML_IMPORT_MAJOR_VERSION = 1
HEADERS += piechart.h
SOURCES += piechart.cpp \
main.cpp
RESOURCES += chapter1-basics.qrc
DESTPATH = $$[QT_INSTALL_EXAMPLES]/qml/tutorials/extending-qml/chapter1-basics
target.path = $$DESTPATH
INSTALLS += target
使用 CMake:
cmake_minimum_required(VERSION 3.16)
project(chapter1-basics LANGUAGES CXX)
set(CMAKE_AUTOMOC ON)
if(NOT DEFINED INSTALL_EXAMPLESDIR)
set(INSTALL_EXAMPLESDIR "examples")
endif()
set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/qml/tutorials/extending-qml/chapter1-basics")
find_package(Qt6 REQUIRED COMPONENTS Core Gui Qml Quick)
qt_add_executable(chapter1-basics
main.cpp
piechart.cpp piechart.h
)
set_target_properties(chapter1-basics PROPERTIES
WIN32_EXECUTABLE TRUE
MACOSX_BUNDLE TRUE
)
target_link_libraries(chapter1-basics PUBLIC
Qt::Core
Qt::Gui
Qt::Qml
Qt::Quick
)
qt_add_qml_module(chapter1-basics
URI Charts
VERSION 1.0
QML_FILES app.qml
NO_RESOURCE_TARGET_PATH
)
install(TARGETS chapter1-basics
RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}"
BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}"
LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}"
)
现在我们可以构建并运行应用程序:

注意:你可能会看到一个警告 Expression ... depends on non-NOTIFYable properties: PieChart::name。这是因为我们给可写的 name 属性添加了一个绑定,但还没有为它定义一个通知信号。因此,如果 name 的值发生变化,QML 引擎将无法更新绑定。这个问题将在后面章节中解决。
本章引用了以下源码:extending-qml/chapter1-basics
第 2 章:与 C++ 方法和信号的连接
假设我们希望 PieChart 有个 “clearChart()” 方法来擦除图表,然后发出 “chartCleared” 信号。app.qml 可以这样调用 clearChart() 并接收 chartCleared() 信号:
import Charts import QtQuick Item { width: 300; height: 200 PieChart { id: aPieChart anchors.centerIn: parent width: 100; height: 100 color: "red" onChartCleared: console.log("The chart has been cleared") } MouseArea { anchors.fill: parent onClicked: aPieChart.clearChart() } Text { anchors { bottom: parent.bottom; horizontalCenter: parent.horizontalCenter; bottomMargin: 20 } text: "Click anywhere to clear the chart" } }

为此,我们在 C++ 类中添加 clearChart() 方法和 chartCleared() 信号:
class PieChart : public QQuickPaintedItem { ... public: ... Q_INVOKABLE void clearChart(); signals: void chartCleared(); ... };
Q_INVOKABLE 的使用使得 clearChart() 方法在 Qt 元对象系统可用,进而可用于 QML。请注意,它可以被声明为 Qt 槽函数而非使用 Q_INVOKABLE,因为槽函数也可以从 QML 调用。这两种方法都是有效的。
clearChart() 方法只是将颜色更改为 Qt::transparent,重新绘制图表,然后发出 chartCleared() 信号:
void PieChart::clearChart() { setColor(QColor(Qt::transparent)); update(); emit chartCleared(); }
现在,当我们运行应用程序并单击窗口时,饼图消失,而应用程序则输出:
qml: The chart has been cleared
本章引用了以下源码:extending-qml/chapter2-methods
第 3 章:添加属性绑定
属性绑定是 QML 的一个强大功能,它允许自动同步不同类型的值。当属性值发生变化时,它使用信号来通知和更新其他类型的值。
让我们为 color 属性启用属性绑定。这意味着如果我们有这样的代码:
import Charts import QtQuick Item { width: 300; height: 200 Row { anchors.centerIn: parent spacing: 20 PieChart { id: chartA width: 100; height: 100 color: "red" } PieChart { id: chartB width: 100; height: 100 color: chartA.color } } MouseArea { anchors.fill: parent onClicked: { chartA.color = "blue" } } Text { anchors { bottom: parent.bottom; horizontalCenter: parent.horizontalCenter; bottomMargin: 20 } text: "Click anywhere to change the chart color" } }

“color: chartA.color” 语句将 chartB 的 color 值与 chartA 的 color 值绑定。每当 chartA 的 color 值发生变化时,chartB 的 color 值也会更新为相同的值。当窗口被点击时,MouseArea 中的 onClicked 处理程序会改变 chartA 的颜色,从而将两个图表都更改为蓝色。
为 color 属性启用属性绑定很容易。我们在其 Q_PROPERTY() 声明中添加了 NOTIFY 特性,以表明每当值发生变化时就会发出 “colorChanged” 信号。
class PieChart : public QQuickPaintedItem { ... Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged) public: ... signals: void colorChanged(); ... };
然后,我们在 setColor() 中发出 colorChanged() 信号:
void PieChart::setColor(const QColor &color) { if (color != m_color) { m_color = color; update(); // repaint with the new color emit colorChanged(); } }
对于 setColor() 来说,在发出 colorChanged() 之前,检查颜色值是否真的发生了变化是很重要的。这可以确保信号不会被不必要地发出,也可以防止其他类型响应值更改时出现循环。
绑定的使用对 QML 来说是至关重要的。如果属性能够被实现,你应该始终为属性添加 NOTIFY 信号,这样你的属性就可以在绑定中使用。不能被绑定的属性不能被自动更新,也不能在 QML 中被灵活地使用。此外,由于绑定在 QML 的使用中被频繁地调用和依赖,如果没有实现绑定,自定义 QML 类型的用户可能会遇到 unexpected behavior。
本章引用了以下源码:extending-qml/chapter3-bindings
第 4 章:使用自定义属性类型
PieChart 目前有一个字符串类型的属性和一个颜色类型的属性。它可以有许多其他类型的属性。例如,它可以有一个 int-type 属性来存储每个图表的标识符:
// C++ class PieChart : public QQuickPaintedItem { Q_PROPERTY(int chartId READ chartId WRITE setChartId NOTIFY chartIdChanged) ... public: void setChartId(int chartId); int chartId() const; ... signals: void chartIdChanged(); }; // QML PieChart { ... chartId: 100 }
除了 int 之外,我们还可以使用其他各种属性类型。QML 自动支持许多 Qt 的数据类型,例如 QColor、QSize 和 QRect。(有关完整列表,请参阅 QML 和 C++ 之间的数据类型转换 文档)
如果我们想创建一个其类型不被 QML 默认支持的属性,我们需要向 QML 引擎注册该类型。
例如,让我们用一个叫做 “PieSlice” 的类型来代替 property 的使用,它有一个 color 属性。我们没有分配颜色,而是分配一个本身包含 color 值的 PieSlice:
import Charts import QtQuick Item { width: 300; height: 200 PieChart { id: chart anchors.centerIn: parent width: 100; height: 100 pieSlice: PieSlice { anchors.fill: parent color: "red" } } Component.onCompleted: console.log("The pie is colored " + chart.pieSlice.color) }
像 PieChart,这个新 PieSlice 类型继承自 QQuickPaintedItem,并且用 Q_PROPERTY() 声明其属性。
class PieSlice : public QQuickPaintedItem { Q_OBJECT Q_PROPERTY(QColor color READ color WRITE setColor) QML_ELEMENT public: PieSlice(QQuickItem *parent = nullptr); QColor color() const; void setColor(const QColor &color); void paint(QPainter *painter) override; private: QColor m_color; };
要在 PieChart 中使用它,我们修改 color 属性声明和相关的方法签名:
class PieChart : public QQuickItem { Q_OBJECT Q_PROPERTY(PieSlice* pieSlice READ pieSlice WRITE setPieSlice) ... public: ... PieSlice *pieSlice() const; void setPieSlice(PieSlice *pieSlice); ... };
定义 setPieSlice() 时需要注意一件事。PieSlice 是一个可视项,所以必须使用 QQuickItem::setParentItem() 将其设置为 PieChart 的子项,这样 PieChart 就知道在绘制其内容时要绘制这个子项:
void PieChart::setPieSlice(PieSlice *pieSlice) { m_pieSlice = pieSlice; pieSlice->setParentItem(this); }
与 PieChart 类型一样,必须使用 QML_ELEMENT 将 PieSlice 类型发布到 QML。
class PieSlice : public QQuickPaintedItem { Q_OBJECT Q_PROPERTY(QColor color READ color WRITE setColor) QML_ELEMENT public: PieSlice(QQuickItem *parent = nullptr); QColor color() const; void setColor(const QColor &color); void paint(QPainter *painter) override; private: QColor m_color; }; ...
与 PieChart 一样,我们将 “Charts” 类型命名空间,版本 1.0,添加到我们的构建文件中:
使用 qmake:
QT += qml quick
CONFIG += qmltypes
QML_IMPORT_NAME = Charts
QML_IMPORT_MAJOR_VERSION = 1
HEADERS += piechart.h \
pieslice.h
SOURCES += piechart.cpp \
pieslice.cpp \
main.cpp
RESOURCES += chapter4-customPropertyTypes.qrc
DESTPATH = $$[QT_INSTALL_EXAMPLES]/qml/tutorials/extending-qml/chapter4-customPropertyTypes
target.path = $$DESTPATH
INSTALLS += target
使用 CMake:
...
qt_add_executable(chapter4-customPropertyTypes
main.cpp
piechart.cpp piechart.h
pieslice.cpp pieslice.h
)
qt_add_qml_module(chapter4-customPropertyTypes
URI Charts
VERSION 1.0
QML_FILES app.qml
NO_RESOURCE_TARGET_PATH
)
...
本章引用了以下源码:extending-qml/chapter4-customPropertyTypes
第 5 章:使用列表属性类型
现在,一个 PieChart 只能有一个 PieSlice。理想情况下,一个 chart 会有多个 slice,有不同的颜色和大小。为此,我们可以设一个 slices 属性,接受 PieSlice 项的列表:
import Charts import QtQuick Item { width: 300; height: 200 PieChart { anchors.centerIn: parent width: 100; height: 100 slices: [ PieSlice { anchors.fill: parent color: "red" fromAngle: 0; angleSpan: 110 }, PieSlice { anchors.fill: parent color: "black" fromAngle: 110; angleSpan: 50 }, PieSlice { anchors.fill: parent color: "blue" fromAngle: 160; angleSpan: 100 } ] } }

为此,我们将 PieChart 中的 pieSlice 属性改为 slices 属性,声明为 QQmlListProperty 类型。QQmlListProperty 类能够在 QML 扩展中创建列表属性。我们用返回 slice 列表的 slices() 函数替换了 pieSlice() 函数,并添加了内部的 append_slice() 函数(在下面讨论)。我们还使用名为 m_slices 的 QList 来存储内部的 slice 列表:
class PieChart : public QQuickItem { Q_OBJECT Q_PROPERTY(QQmlListProperty<PieSlice> slices READ slices) ... public: ... QQmlListProperty<PieSlice> slices(); private: static void append_slice(QQmlListProperty<PieSlice> *list, PieSlice *slice); QString m_name; QList<PieSlice *> m_slices; };
尽管 slices 属性没有相关的 WRITE 函数,但由于 QQmlListProperty 的工作方式,它仍然是可修改的。在 PieChart 的实现中,我们实现了 PieChart::slices() 来返回 QQmlListProperty 的值,并表明每当 QML 发出向列表添加项目的请求时,内部的 PieChart::append_slice() 函数将被调用:
QQmlListProperty<PieSlice> PieChart::slices() { return QQmlListProperty<PieSlice>(this, nullptr, &PieChart::append_slice, nullptr, nullptr, nullptr, nullptr, nullptr); } void PieChart::append_slice(QQmlListProperty<PieSlice> *list, PieSlice *slice) { PieChart *chart = qobject_cast<PieChart *>(list->object); if (chart) { slice->setParentItem(chart); chart->m_slices.append(slice); } }
append_slice() 函数还是像之前那样设置父项,并将新项添加到 m_slices 列表中。QQmlListProperty 的 append 函数是用两个参数调用的:列表属性和要附加的项目。
PieSlice 类也被修改为包含 fromAngle 和 angleSpan 属性,并根据这些值绘制 slice。如果你已阅读本教程的前几页,这是一个简单的修改,所以此处不显示代码。
本章引用了以下源码:extending-qml/chapter5-listproperties
第 6 章:编写扩展插件
目前,PieChart 和 PieSlice 类型由 app.qml 使用,在 C++ 应用程序中使用 QQuickView 显示。使用我们的 QML 扩展的另一种方法是创建一个插件库,把它当作新的 QML 导入模块提供给 QML 引擎。这使 PieChart 和 PieSlice 类型被注册到一个类型命名空间,可以被任何 QML 应用程序导入,而非限制这些类型只能被一个应用程序使用。
创建插件的步骤在 为 QML 创建 C++ 插件 中描述。首先,我们创建一个名为 ChartsPlugin 的插件类。它继承 QQmlEngineExtensionPlugin,并使用 Q_PLUGIN_METADATA() 宏将插件注册到 Qt 元对象系统中。
这是 chartsplugin.h 中的 ChartsPlugin 定义:
#include <QQmlEngineExtensionPlugin> class ChartsPlugin : public QQmlEngineExtensionPlugin { Q_OBJECT Q_PLUGIN_METADATA(IID QQmlEngineExtensionInterface_iid) };
然后,我们配置构建文件,将该项目定义为插件库。
使用 qmake:
TEMPLATE = lib
CONFIG += plugin qmltypes
QT += qml quick
QML_IMPORT_NAME = Charts
QML_IMPORT_MAJOR_VERSION = 1
TARGET = $$qtLibraryTarget(chartsplugin)
HEADERS += piechart.h \
pieslice.h \
chartsplugin.h
SOURCES += piechart.cpp \
pieslice.cpp
DESTPATH=$$[QT_INSTALL_EXAMPLES]/qml/tutorials/extending-qml/chapter6-plugins/$$QML_IMPORT_NAME
target.path=$$DESTPATH
qmldir.files=$$PWD/qmldir
qmldir.path=$$DESTPATH
INSTALLS += target qmldir
CONFIG += install_ok # Do not cargo-cult this!
OTHER_FILES += qmldir
# Copy the qmldir file to the same folder as the plugin binary
cpqmldir.files = qmldir
cpqmldir.path = .
COPIES += cpqmldir
使用 CMake:
qt6_add_qml_module(chartsplugin
VERSION 1.0
URI "Charts"
PLUGIN_TARGET chartsplugin
)
target_sources(chartsplugin PRIVATE
piechart.cpp piechart.h
pieslice.cpp pieslice.h
)
target_link_libraries(chartsplugin PRIVATE
Qt::Core
Qt::Gui
Qt::Qml
Qt::Quick
)
if(QT6_IS_SHARED_LIBS_BUILD AND APPLE)
get_target_property(is_bundle chapter6-plugins MACOSX_BUNDLE)
if(is_bundle)
# The application's main.cpp adds an explicit QML import path to look for qml modules under
# a PlugIns subdirectory in a macOS bundle.
# Copy the qmldir and shared library qml plugin.
set(charts_dir "$<TARGET_FILE_DIR:chartsplugin>")
set(chars_qmldir_file "${charts_dir}/qmldir")
set(app_dir "$<TARGET_FILE_DIR:chapter6-plugins>")
set(bundle_charts_dir "${app_dir}/../PlugIns/Charts")
add_custom_command(TARGET chartsplugin POST_BUILD
COMMAND ${CMAKE_COMMAND} -E make_directory ${bundle_charts_dir}
COMMAND ${CMAKE_COMMAND} -E copy_if_different
$<TARGET_FILE:chartsplugin> ${bundle_charts_dir}
COMMAND ${CMAKE_COMMAND} -E copy_if_different
${chars_qmldir_file} ${bundle_charts_dir}
VERBATIM
)
endif()
endif()
set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLEDIR}/Charts")
install(TARGETS chartsplugin
RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}"
BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}"
LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}"
)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/qmldir
DESTINATION "${INSTALL_EXAMPLEDIR}")
在 Windows 或 Linux 上构建该示例时,Charts 目录将与使用我们新导入模块的应用程序位于同一级别。这样,QML 引擎会找到我们的模块,因为 QML 导入的默认搜索路径包括应用程序的可执行目录。在 macOS 上,插件的二进制文件被复制到应用程序包中的 Contents/PlugIns。在 qmake 中,此路径设置在 chapter6-plugins/app.pro:
macos:!qtConfig(static) {
charts.files = $$OUT_PWD/Charts
charts.path = Contents/PlugIns
QMAKE_BUNDLE_DATA += charts
}
考虑到这一点,我们还需要在 main.cpp 中添加此位置作为 QML 导入路径:
QQuickView view;
#ifdef Q_OS_OSX
view.engine()->addImportPath(app.applicationDirPath() + "/../PlugIns");
#endif
...
当有多个应用程序使用相同的 QML 导入时,定义自定义导入路径也很有用。
.pro 文件还包含额外的魔法,以确保 模块定义 qmldir 文件 始终复制到与插件二进制文件相同的位置。
qmldir 文件声明了模块名称和模块可用的插件:
module Charts linktarget chartsplugin optional plugin chartsplugin classname ChartsPlugin typeinfo chartsplugin.qmltypes prefer :/Charts/
现在我们有了一个 QML 模块,只要QML引擎知道在哪里可以找到它,它就可以被导入到任何应用程序。该示例包含加载 app.qml 的可执行文件,它使用 import Charts 1.0 语句。另外,你可以使用 qml 工具 加载 QML 文件,将导入路径设置为当前目录,这样它就能找到 qmldir 文件:
qml -I . app.qml
“Charts” 模块将由 QML 引擎加载,该模块提供的类型将可用于任何导入它的 QML 文档。
本章引用了以下源码:extending-qml/chapter6-plugins
第 7 章:总结
在本教程中,我们展示了创建 QML 扩展的基本步骤:
- 通过继承 QObject 并使用 QML_ELEMENT 或 QML_NAMED_ELEMENT() 注册来定义新的 QML 类型
- 使用 Q_INVOKABLE 或 Qt 槽函数添加可调用的方法,并使用
onSignal语法连接 Qt 信号 - 通过定义 NOTIFY 信号添加属性绑定
- 如果内置类型不够用,可以定义自定义属性类型
- 使用 QQmlListProperty 定义列表属性类型
- 通过定义 Qt 插件并编写 qmldir 文件来创建插件库
QML 和 C++ 集成概述 文档显示了可以添加到 QML 扩展中的其他有用功能。例如,我们可以使用 默认属性 可以在不使用 slices 属性的情况下添加 slice:
PieChart {
PieSlice { ... }
PieSlice { ... }
PieSlice { ... }
}
或者使用 property value sources 不时地随机添加和删除 slice:
PieChart {
PieSliceRandomizer on slices {}
}