当前位置: 首页 > news >正文

QML与C++交互

QML 与 C++ 的交互是 Qt Quick 开发的核心需求,常用于将界面逻辑与底层业务逻辑解耦。

一、基础交互原理

  • 核心机制‌:通过 Qt 元对象系统(Meta-Object System)实现 QML 与 C++ 的双向通信,依赖信号槽(Signals & Slots)和属性绑定(Property Binding)‌。
    注册方式:qml中setContextProperty、qt c++中qmlRegisterType
        QQmlApplicationEngine engine;
        MyObject myObject;
        engine.rootContext()->setContextProperty("myObject", &myObject);
    qmlRegisterType<MyObject>("MyObjectLib", 1, 0, "MyObject");
  • 数据类型映射‌:QML 自动转换基础类型(如 intQString),复杂类型需注册为元类型(如 QJsonObject)‌。

二、常见交互方式 

1、暴露 C++ 对象到 QML 上下文。

cpp

// C++ 类
class DataManager : public QObject {
    Q_OBJECT
public:
    Q_INVOKABLE void saveData(const QString &content); 
};

// 主函数中注册
int main() {
    QGuiApplication app(argc, argv);
    QQmlApplicationEngine engine;
    
    DataManager manager;
    engine.rootContext()->setContextProperty("dataManager", &manager); // 关键步骤
    
    engine.load(QUrl("qrc:/main.qml"));
    return app.exec();
}

qml

// QML 调用
Button {
    onClicked: dataManager.saveData("Hello QML!")
}
2、注册 C++ 类为 QML 类型。

cpp

// 定义可导出的 C++ 类
class Calculator : public QObject {
    Q_OBJECT
    Q_PROPERTY(int result READ result NOTIFY resultChanged) // 属性暴露
public:
    Q_INVOKABLE int add(int a, int b) { return a + b; }
signals:
    void resultChanged();
private:
   int result;
};

// 在 main.cpp 注册
qmlRegisterType<Calculator>("MyLib", 1, 0, "Calculator");

qml

// QML 中使用
import MyLib 1.0

Calculator {
    id: calc
    onResultChanged: console.log("New result:", result)
}

Button {
    onClicked: calc.result = calc.add(10, 20)
}
3、使用 QJSValue 传递函数,异步回调。

cpp

class CallbackHandler : public QObject {
    Q_OBJECT
public:
    Q_INVOKABLE void registerCallback(QJSValue func) {
        m_callback = func;
    }
    void trigger() {
        if (m_callback.isCallable()) 
            m_callback.call();
    }
private:
    QJSValue m_callback;
};

qml

// QML 传递回调函数
CallbackHandler {
    id: handler
    Component.onCompleted: handler.registerCallback(() => console.log("Called!"))
}
4、通过 Q_PROPERTY 实现属性绑定,自动同步 C++ 与 QML 的数值变化。

cpp

class Settings : public QObject {
    Q_OBJECT
    Q_PROPERTY(bool darkMode READ darkMode WRITE setDarkMode NOTIFY darkModeChanged)
public:
    bool darkMode() const { return m_darkMode; }
    void setDarkMode(bool enabled) { 
        if (m_darkMode != enabled) {
            m_darkMode = enabled;
            emit darkModeChanged();
        }
    }
signals:
    void darkModeChanged();
private:
    bool m_darkMode = false;
};

 qml

// QML 双向绑定
Switch {
    checked: settings.darkMode
    onCheckedChanged: settings.darkMode = checked
}

三、实例

1、实例(qml中setContextProperty注册方式)

1)、创建一个空的Qt Quick程序。创建后,基本目录结构如下:

2)、打开main.cpp,进行修改。

#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include <QObject>
#include <QDebug>

class MyObject : public QObject
{
    Q_OBJECT
    Q_PROPERTY(QString message READ message WRITE setMessage NOTIFY messageChanged)
public:
    QString message() const {
        return m_message;
    }
    void setMessage(const QString& qMsg){
        m_message = qMsg;
    }

public slots:
    void sayHello() {
        m_message = "Hello from C++!";
        qDebug() << m_message; // 终端中打印
        emit messageChanged();
    }

signals:
    void messageChanged();

private:
    QString m_message="hello init";
};

int main(int argc, char *argv[])
{
    QGuiApplication app(argc, argv);

    QQmlApplicationEngine engine;

    MyObject myObject;
    engine.rootContext()->setContextProperty("myObject", &myObject);

    const QUrl url(QStringLiteral("qrc:/main.qml"));
    QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
                     &app, [url](QObject *obj, const QUrl &objUrl) {
        if (!obj && url == objUrl)
            QCoreApplication::exit(-1);
    }, Qt::QueuedConnection);
    engine.load(url);

    return app.exec();
}

#include "main.moc"

3)、打开main.qml,进行修改。

import QtQuick 2.9
import QtQuick.Window 2.2
import QtQuick.Controls 2.2

ApplicationWindow {
    visible: true
    width: 400
    height: 300
    title: "QML and C++ Interaction"

    Button {
        text: "Click Me"
        onClicked: {
            myObject.sayHello(); // 调用C++对象的函数
            console.log("调用C++对象的函数\n");
        }
    }

    Label {
           id: label1
            visible: true
            text: myObject.message // 显示从C++传递的消息
            anchors.centerIn: parent
        }
}

4)、生成效果如下:

2、实例(qt c++中qmlRegisterType注册方式)

1)、创建一个空的Qt Quick程序。创建后,基本目录结构如下:

2)、打开main.cpp,进行修改。

#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include <QObject>
#include <QDebug>

class MyObject : public QObject
{
    Q_OBJECT
    Q_PROPERTY(QString message READ message WRITE setMessage NOTIFY messageChanged)
public:
    QString message() const {
        return m_message;
    }
    void setMessage(const QString& qMsg){
        m_message = qMsg;
    }

public slots:
    void sayHello() {
        m_message = "Hello from C++!";
        qDebug() << m_message; // 终端中打印
        emit messageChanged();
    }

signals:
    void messageChanged();

private:
    QString m_message="hello init";
};

int main(int argc, char *argv[])
{
    QGuiApplication app(argc, argv);

    QQmlApplicationEngine engine;

    qmlRegisterType<MyObject>("MyObjectLib", 1, 0, "MyObject");

    const QUrl url(QStringLiteral("qrc:/main.qml"));
    QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
                     &app, [url](QObject *obj, const QUrl &objUrl) {
        if (!obj && url == objUrl)
            QCoreApplication::exit(-1);
    }, Qt::QueuedConnection);
    engine.load(url);

    return app.exec();
}

#include "main.moc"

3)、打开main.qml,进行修改。

import QtQuick 2.9
import QtQuick.Window 2.2
import QtQuick.Controls 2.2
import MyObjectLib 1.0


ApplicationWindow {
    visible: true
    width: 400
    height: 300
    title: "QML and C++"

    MyObject{
        id: testObj
    }

    Button {
        text: "Click Me"
        onClicked: {
            testObj.sayHello(); // 调用C++对象的函数
            console.log("调用C++对象的函数\n");
        }
    }

    Label {
           id: label1
            visible: true
            text: testObj.message // 显示从C++传递的消息
            anchors.centerIn: parent
        }
}

4)、生成效果如下:

 

相关文章:

  • Flink读取Kafka数据写入IceBerg(HiveCatalog)
  • 汽车一键启动系统使用方便,舒适出行,轻松匹配
  • Java 中线程废弃方法(stop、suspend、resume)原因及替代方案
  • 2025年春季学期《算法分析与设计》练习4
  • 碰一碰发视频saas系统技术源头一站式开发文档
  • Tomcat虚拟主机配置详解:Centos环境下多域名部署(详细教程!)
  • 输入输出 数组 冒泡排序举例
  • 基于Spring Boot的大学校园生活信息平台的设计与实现(LW+源码+讲解)
  • 机器学习之支持向量机(SVM)算法详解
  • docker 的volumes如何清理
  • SpringBoot的启动原理?
  • ubuntu中的ens33网卡在ifconfig中被默认关闭了?
  • c语言笔记 存储期
  • Topaz Photo AI for Mac v3.5.2图像质量增强 支持M、Intel芯片
  • python-列表的操作以及切片
  • 异常(完)
  • 计算GPS点之间距离(JS实现)
  • 从C语言开始的C++编程生活(1)
  • 第二十七篇 数据仓库与维度建模指南:从理论到实战的进阶之路
  • 无需OpenAI API运行OpenManus!
  • 玛丽亚·凯莉虹口连唱两夜,舞台绽放唤醒三代人青春记忆
  • 新闻1+1丨强对流天气频繁组团来袭,该如何更好应对?
  • 英国6月初将公布对华关系的审计报告,外交部:望英方树立正确政策导向
  • 银行积分大幅贬值遭质疑,涉及工行、中行、农行等
  • 九江宜春领导干部任前公示,3人拟提名为县(市、区)长候选人
  • 湖北宜化拟斥资超32亿加价回购“弃子”,布局上游煤炭业务