使用 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 {} }