QML(Qt Meta Language 或 Qt Modeling Language)是 Qt 框架中用于描述用户界面的声明式语言,它非常适合用来构建流畅、动态的应用程序界面。C++ 则常被用来实现应用程序的核心逻辑和性能关键部分。为了充分利用两者的优势,Qt 提供了多种方式让 QML 和 C++ 之间进行交互。
1, 使用 Q_INVOKABLE 关键字
通过在 C++ 类中使用 Q_INVOKABLE 关键字,可以使得该方法能够直接从 QML 中调用。首先,你需要确保这个类继承自 QObject 并且使用了 Q_OBJECT 宏。
cpp
#pragma once
#include <QObject>
class MyWidget : public QObject
{
Q_OBJECT
public:
MyWidget(QObject*parent = nullptr);
~MyWidget();
Q_INVOKABLE QString myInvokableMethod(const QString& input) {
return "Hello, ccccc" + input;
}
};
cpp
#include "MyWidget.h"
MyWidget::MyWidget(QObject*parent)
: QObject(parent)
{
}
MyWidget::~MyWidget()
{}
Main函数中
cpp
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include "MyWidget.h"
#include <QQmlContext>
int main(int argc, char *argv[])
{
#if defined(Q_OS_WIN) && QT_VERSION_CHECK(5, 6, 0) <= QT_VERSION && QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
#endif
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
MyWidget myObject;
engine.rootContext()->setContextProperty("myCppObject", &myObject); // 设置上下文属性
//qmlRegisterType<MyWidget>("com.example.myclass", 1, 0, "MyWidget"); // 注册类型
engine.load(QUrl(QStringLiteral("qrc:/qt/qml/qtquickapplicationtest01/main.qml")));
if (engine.rootObjects().isEmpty())
return -1;
return app.exec();
}
qml调用
cpp
import QtQuick 2.9
import QtQuick.Window 2.2
//import com.example.myclass 1.0 // 导入我们注册的模块
Window {
visible: true
width: 640
height: 480
title: "QtQuickApplicationTest01"
//MyWidget { id: myCppObject } // 创建C++类的实例
Text {
anchors.fill: parent
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
font.bold: true
font.pointSize: 42
text: "Hello World!"
MouseArea {
anchors.fill: parent
onClicked: {
console.log(myCppObject.myInvokableMethod("World")) // 调用可调用方法
}
}
}
}
该方法只在main中创建一次,不适用多次
2,注册方式
main函数中
cpp
qmlRegisterType<MyWidget>("com.example.myclass", 1, 0, "MyWidget"); // 注册类型
调用过程
cpp
import QtQuick 2.9
import QtQuick.Window 2.2
import com.example.myclass 1.0 // 导入我们注册的模块
Window {
visible: true
width: 640
height: 480
title: "QtQuickApplicationTest01"
MyWidget { id: myCppObject } // 创建C++类的实例
Text {
anchors.fill: parent
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
font.bold: true
font.pointSize: 42
text: "Hello World!"
MouseArea {
anchors.fill: parent
onClicked: {
console.log(myCppObject.myInvokableMethod("World")) // 调用可调用方法
}
}
}
}
该方法可以创建多个实例
3,使用是 Qt 的宏 Q_PROPERTY,它的作用是:将 C++ 类中的一个属性暴露给 Qt 的元对象系统(Meta-Object System),从而可以在 QML 中直接访问和绑定这个属性。
如下代码
cpp
#pragma once
#include <QObject>
class MyWidget : public QObject
{
Q_OBJECT
public:
MyWidget(QObject*parent = nullptr);
~MyWidget();
Q_PROPERTY(QString message READ message WRITE setMessage NOTIFY messageChanged)
Q_INVOKABLE QString myInvokableMethod(const QString& input) {
return "Hello, ccccc" + input;
}
QString message() const;
void setMessage(const QString& message);
signals:
void messageChanged();
private:
QString m_message;
};
cpp
#include "MyWidget.h"
#include <qDebug>
MyWidget::MyWidget(QObject*parent)
: QObject(parent)
{
}
MyWidget::~MyWidget()
{}
QString MyWidget::message() const
{
return m_message;
}
void MyWidget::setMessage(const QString& message)
{
if (m_message != message) {
m_message = message;
emit messageChanged();
qDebug() << "Signal emitted:";
}
}
cpp
import QtQuick 2.9
import QtQuick.Window 2.2
import QtQuick.Controls 2
import com.example.myclass 1.0 // 导入我们注册的模块
Window {
visible: true
width: 640
height: 480
title: "QtQuickApplicationTest01"
MyWidget {
id: myCppObject
/*
onMessageChanged: {
console.log("Direct connection: message changed!")
parent.text = "Received: " + myCppObject.message
}
*/
}
Connections {
target: myCppObject
onMessageChanged: {
console.log("1234")
}
}
Column
{
spacing:30
Text {
font.bold: true
font.pointSize: 42
text: "Hello World!"
MouseArea {
anchors.fill: parent
onClicked: {
myCppObject.message = "Hello from QML!"
}
}
}
Label {
id: label
text:"change message"
font.pointSize: 42
MouseArea {
anchors.fill: parent
onClicked: {
label.text= myCppObject.message
}
}
}
}
}