前言
在 QT 中 既然 qml处理前端,C++处理后端,那么 C++ 和 QML 是如何进行交互?
将对象暴露给 qml
void QQmlContext::setContextProperty(const QString &name, QObject *value)
Set the value of the name property on this context.
QQmlContext does not take ownership of value.
这样在 qml 中可以通过 name对象直接使用对象的属性或者方法。
- 对象的方法 要求必须是 公共的槽函数,或者是被
Q_INVOKABLE
修饰的普通公有函数。代码如下
//MyClass.cpp
#ifndef MYCLASS_H
#define MYCLASS_H
#include <QObject>
class MyClass : public QObject
{
Q_OBJECT
public:
explicit MyClass(QObject *parent = nullptr);
Q_INVOKABLE int sum(int a, int b);
signals:
public slots:
void print();
};
#endif // MYCLASS_H
//main.cpp
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include "MyClass.h"
int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication app(argc, argv);
MyClass *myClass = new MyClass;
QQmlApplicationEngine engine;
QQmlContext *context = engine.rootContext();
context->setContextProperty("myClass", myClass);
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
if (engine.rootObjects().isEmpty())
return -1;
return app.exec();
}
import QtQuick 2.9
import QtQuick.Window 2.2
Window {
visible: true
width: 640
height: 480
title: qsTr("Hello World")
Component.onCompleted: {
myClass.print();
console.log(myClass.sum(1, 2));
}
}
将C++中类的属性暴露给qml。使用 Q_PROPERTY(...)
进行暴露
class Message : public QObject
{
Q_OBJECT
Q_PROPERTY(QString author READ author WRITE setAuthor NOTIFY authorChanged)
public:
void setAuthor(const QString &a) {
if (a != m_author) {
m_author = a;
emit authorChanged();
}
}
QString author() const {
return m_author;
}
signals:
void authorChanged();
private:
QString m_author;
};
int main(int argc, char *argv[]) {
QGuiApplication app(argc, argv);
QQuickView view;
Message msg;
view.engine()->rootContext()->setContextProperty("msg", &msg);
view.setSource(QUrl::fromLocalFile("MyItem.qml"));
view.show();
return app.exec();
}
// MyItem.qml
import QtQuick 2.0
Text {
width: 100; height: 100
text: msg.author // invokes Message::author() to get this value
Component.onCompleted: {
msg.author = "Jonah" // invokes Message::setAuthor()
}
}
注意 这句话 QQmlContext does not take ownership of value. 也就是说 在使用 setContextProperty 应该注意暴露对象的生命周期。
在QML中注册C++对象
qmlRegisterType<Person>("LiBai.Person", 1, 0, "Person");
//person.cpp
#include "Person.h"
#include <QDebug>
Person::Person(QObject *parent) : QObject(parent), m_name(QStringLiteral("小明")), m_age(18)
{
}
void Person::print()
{
qDebug() << "name : " << m_name << " age : " << m_age;
}
//Person.h
#ifndef PERSON_H
#define PERSON_H
#include <QObject>
#include <QString>
class Person : public QObject
{
Q_OBJECT
Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged)
Q_PROPERTY(int age READ age WRITE setAge NOTIFY ageChaged)
public:
explicit Person(QObject *parent = nullptr);
Q_INVOKABLE void print();
QString name() const
{
return m_name;
}
int age() const
{
return m_age;
}
signals:
void nameChanged(QString name);
void ageChaged(int age);
public slots:
void setName(QString name)
{
if (m_name == name)
return;
m_name = name;
emit nameChanged(m_name);
}
void setAge(int age)
{
if (m_age == age)
return;
m_age = age;
emit ageChaged(m_age);
}
private:
QString m_name;
int m_age;
};
#endif // PERSON_H
main.qml
import QtQuick 2.9
import QtQuick.Window 2.2
import QtQuick.Layouts 1.3
import LiBai.Person 1.0
Window {
visible: true
width: 640
height: 480
title: qsTr("Hello World")
Item{
id: rootItem
anchors.fill: parent
ColumnLayout{
id: columnLayout
anchors.fill: parent
Rectangle{
id: rect
Layout.preferredHeight: 240
Layout.preferredWidth: columnLayout.width
Layout.fillHeight: true
color: "blue"
Text{
anchors.centerIn: parent
color: "white"
text: person.name + " " + person.age
}
Person{
id: person
name: "老王"
age: 23
}
}
Rectangle{
id: rect_1
Layout.preferredHeight: 240
Layout.preferredWidth: columnLayout.width
Layout.fillHeight: true
color: "red"
Text{
anchors.centerIn: parent
color: "white"
text: person_1.name + " " + person_1.age
}
Person{
id: person_1
}
}
}
}
}
注意: 在写完 如下代码后 Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged)
可以将鼠标光标放在 Q_PROPERTY
上,然后 组合键alt + enter
QtCreator就可以自动生成代码。在QML中注册C++类型适合于要重复使用的情况