QML与C++交互的方式

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
                }
            }
        }
    }

}
相关推荐
青少儿编程课堂1 小时前
蓝桥杯青少组图形化 + 全国青少年信息素养大赛 + 电子学会Scratch考级:校园连连看解析
c++·python·算法·bfs·信息学竞赛
草莓熊Lotso1 小时前
【C++ 基于微服务的即时通讯系统】文件存储子服务实战:UUID生成、文件IO封装与全接口单元测试
开发语言·网络·数据库·c++·微服务·架构·单元测试
huaqianzkh3 小时前
WinForm C#:循环修改控件UI闪烁卡顿?SuspendLayout / ResumeLayout 与 BeginUpdate 优化
开发语言·ui·c#
沐晓时光13 小时前
C语言入门,内存函数知识讲解
c语言·开发语言
David猪大卫19 小时前
【C++修炼】map 和 set 的使用
c语言·开发语言·数据结构·c++·经验分享·笔记·学习
HPtiger19 小时前
C++ 入门笔记:从 C 到 C++ 的核心过渡(命名空间、输入输出、缺省参数、重载、引用、内联)
c语言·c++·学习
fengci.20 小时前
CTF2MISC中等部分
开发语言·前端·学习
xys_6781 天前
JavaEE通关手册:初识Java
java·开发语言
努力努力再努力wz1 天前
【Lua 进阶系列】从 C++ 对象到 Lua 变量:一文理解 userdata、Lua 栈与元表绑定机制
c++·junit·lua
慧都产品智能化1 天前
Qt 表格升级攻略:复用已有编辑器,减少重复开发
c++·qt·编辑器·qt6.3