概述
由于QML引擎与Qt元对象系统的紧密集成,任何由QObject派生出来的类其公有的接口或属性都可以从QML代码中轻松访问,并且改动的地方很少,就可以让C++代码定义的功能轻松扩展QML。
任何QML代码都可以访问QObject派生类的实例的以下成员:
- 属性
- 方法(用Q_INVOKABLE标记)
- 信号
另外,如果用Q_ENUMS声明了枚举,那么枚举也是可以直接调用的。
通常来说,QObject类派生于QML类型系统中,都可以从QML访问,但是如果要访问其他类型信息的方式使用某个类,例如,如果该类本身将用作方法参数或属性,那么该类需要注册才能使用,后期将会写相关的文章进行介绍。
Q_PROPERTY()
要想在 QML中调用到 C++的属性,就需要用到Q_PROPERTY宏,该宏就是将 C++属性暴露给QML 调用。
下面来看个简单示例:
首先新建一个类继承于 QObject
#include <QObject>
class Student : public QObject
{
Q_OBJECT
Q_PROPERTY(QString name READ getName WRITE setName NOTIFY sigNameChanged)
public:
explicit Student(QObject *parent = nullptr);
~Student(){}
void setName(const QString & name){
if(name != m_name){
m_name = name;
emit sigNameChanged(m_name);
}
}
QString getName() const {return m_name;}
signals:
void sigNameChanged(QString name);
private:
QString m_name;
};
该类中用Q_PROPERTY宏将 name 属性暴露出来供 QML 调用。
然后在 main 函数中进行上下文属性注册
int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
Student student;
engine.rootContext()->setContextProperty("student", &student);
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
if (engine.rootObjects().isEmpty())
return -1;
return app.exec();
}
然后在 QML 中进行调用
Window {
visible: true
width: 640
height: 480
Label{
anchors.centerIn: parent
text: student.name
}
Connections{
target: student
onSigNameChanged:{
console.log("student name changed",name)
}
}
Component.onCompleted: {
student.name = "xiaoming"
}
}
为了与QML实现最大的互操作性,任何可写的属性应该有一个关联的NOTIFY信号,每当属性值发生变化时就会发出。
在页面加载完成后Component.onCompleted中去修改 student 的属性,这时候会自动触发信号sigNameChanged,这里将信号连接起来,看看输出效果:
qml: student name changed xiaoming
这就从 QML 轻松的调用到了 C++ 中的属性。
本文就只介绍将简单的 C++系统属性提供给 QML 中调用,后期将介绍更多的类型提供给 QML 使用。
本文示例代码在这里,点击下载。