使用 Context Properties 将 C++ 对象嵌入 QML

将 QML 对象加载到 C++ 应用程序时,直接嵌入一些可在 QML 代码中使用的 C++ 数据会很有用。例如,这使得可以对嵌入式对象调用 C++ 方法,或将 C++ 对象实例用作 QML 视图的数据模型。

QQmlContext 类可以将 C++ 数据注入到 QML 对象中,能够将 C++ 的数据暴露给 QML 对象的上下文,如此我们便能够在 QML 代码中取到来自于 C++ 的数据。

设置一个简单的 Context Property

该段以下面的代码为例来讲解如何设置简单的 Context Property,实现数据共享:

 // MyItem.qml
 import QtQuick 2.0

 Text { text: currentDateTime }

上面的这一行代码中的 text 属性引用了一个当前作用域中并不存在的 currentDateTime 变量值。我们希望这个值是从构建当前 qml 组件的 C++ 代码中传过来的。这要用到 QQmlContext::setContextProperty()

 QQuickView view;
 view.rootContext()->setContextProperty("currentDateTime", QDateTime::currentDateTime());
 view.setSource(QUrl::fromLocalFile("MyItem.qml"));
 view.show();

注意:QML 中所有表达式求值的过程都是在特定的上下文中进行的,如果上下文有变动,那么该上下文中的所有绑定都会被重新求值。因此,在除了应用初始化之外的地方都要小心使用 context properties,因其有可能导致应用性能下降。

将一个对象设置为 Context Property

Context properties 可以存储 QVariantQObject* 值。这意味着自定义的 C++ 对象也可以使用这种方式注入上下文,实现在 QML 中直接读写。在下面的例子中,我们将一个 QObject 实例嵌入 QML ,然后在 QML 中调用一个该实例的成员方法:

C++
 class ApplicationData : public QObject
 {
     Q_OBJECT
 public:
     Q_INVOKABLE QDateTime getCurrentDateTime() const {
         return QDateTime::currentDateTime();
     }
 };

 int main(int argc, char *argv[]) {
     QGuiApplication app(argc, argv);

     QQuickView view;

     ApplicationData data;
     view.rootContext()->setContextProperty("applicationData", &data);

     view.setSource(QUrl::fromLocalFile("MyItem.qml"));
     view.show();

     return app.exec();
 }
QML
 // MyItem.qml
 import QtQuick 2.0

 Text { text: applicationData.getCurrentDateTime() }

(注意:从 C++ 返回给 QML 的 date/time 值可以用 Qt.formatDateTime() 和相关函数格式化)

QML item 可以使用 Connections 类型连接到 context property,实现信号接收。例如:若 ApplicationData 有一个名为 dataChanged() 的信号,该信号则可以在 Connections 对象中与 onDataChanged 处理函数相连接,示例如下:

 Text {
     text: applicationData.getCurrentDateTime()

     Connections {
         target: applicationData
         onDataChanged: console.log("The application data changed!")
     }
 }

Context properties 在 QML view 中使用 C++ 数据模型的场景中非常有用。参考下面的例子:

这些例子演示了如何在 QML view 中使用基于 QStringListQList<QObject*> 的数据模型和 QAbstractItemModel

另推荐阅读 QQmlContext 介绍文档,获取更多信息。