当在 C++ 应用中加载 QML 对象时,通常都会有在 QML 和 C++ 之间进行交互和共享数据的需求。
通过 QQmlContext 类可以将 C++ 数据注入到 QML 对象中: QQmlContext 能够将 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;
// 下面这样就将 QDateTime::currentDateTime() 暴露为了 qml 上下文中的一个可读取(求值)的属性
view.rootContext()->setContextProperty("currentDateTime", QDateTime::currentDateTime());
view.setSource(QUrl::fromLocalFile("MyItem.qml"));
view.show()
注意:QML 中所有表达式求值的过程都是在特定的上下文中进行的,如果上下文有变动,那么该上下文中的所有绑定都会被重新求值。因此,在除了应用初始化之外的地方都要小心使用 context properties ,因其有可能导致应用性能下降.
将一个对象设置为 Context Property
Context properties 可以存储 QVariant 或 QObject* 值。这意味着自定义的 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::fromLoacaFile("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("App data changed!")
}
}
Context properties 在 QML view 中使用 C++ 数据模型的场景中非常有用。参考下面的例子:
这些例子演示了如何在 QML view 中使用基于 QStringList, QList<QObject*> 的数据模型和 QAbstractItemModel 。
另推荐阅读 QQmlContext 原文 (译文)介绍文档,获取更多信息