Qml与C++交互

8 篇文章 0 订阅

Qml与C++交互

文档如是说,使用C ++代码中定义的功能可以轻松扩展QML。
由于QML引擎与Qt元对象系统的紧密集成,可以从QML代码访问由QObject派生的类适当公开的任何功能。
这使得C ++类的属性和方法可以直接从QML访问,通常很少或无需修改。

QML引擎能够通过元对象系统内省QObject实例。
这意味着,

  • 任何QML代码都可以访问QObject派生类实例的以下成员:
    • 属性(使用Q_PROPERTY注册的属性)
    • 方法(需注册为public slots或是标记为Q_INVOKABLE)
    • 信号
      (此外,如果已使用Q_ENUMS声明枚举,则可以使用枚举。)

通常,无论是否已向QML类型系统注册了QObject派生类,都可以从QML访问它们。
但是,如果QML引擎要访问其他类型信息(例如,如果要将类本身用作方法参数或属性,或者要将其中一个枚举类型用于以这种方式使用),那么该类可能需要注册。

QML中调用C++类型

例子

颜色改变例子
新建一个ColorMaker类
colormaker.h文件如下:

#ifndef COLORMAKER_H
#define COLORMAKER_H

#include <QObject>
#include <QColor>
#include <QTimerEvent>

class ColorMaker : public QObject
{
    Q_OBJECT

    Q_ENUMS(GenerateAlgorithm)
    Q_PROPERTY(QColor color READ getColor WRITE setColor NOTIFY colorChanged)
    Q_PROPERTY(QColor timeColor READ timeColor)

public:
    explicit ColorMaker(QObject *parent = 0);

    enum GenerateAlgorithm
    {
        RandomRGB,
        RandomRed,
        RandomBlue,
        RandomGreen,
        LinearIncrease
    };

    QColor getColor() const;
    void setColor(const QColor &color);
    QColor timeColor() const;

    Q_INVOKABLE GenerateAlgorithm algorithm() const;
    Q_INVOKABLE void setAlgorithm(GenerateAlgorithm algorithm);

signals:
    void colorChanged(const QColor &color);
    void currentTime(const QString &timeStr);

public slots:
    void start();
    void stop();

protected:
    void timerEvent(QTimerEvent *e);

private:
    GenerateAlgorithm m_algorithm;
    QColor m_currentColor;
    int m_nColorTimer;
};

#endif // COLORMAKER_H

colormaker.cpp文件

#include "colormaker.h"
#include <QDateTime>

ColorMaker::ColorMaker(QObject *parent) : QObject(parent),
    m_algorithm(RandomRGB),
    m_currentColor(Qt::black),
    m_nColorTimer(0)
{
    qsrand(QDateTime::currentDateTime().toTime_t());
}

QColor ColorMaker::getColor() const
{
    return m_currentColor;
}

void ColorMaker::setColor(const QColor &color)
{
    m_currentColor = color;
}

QColor ColorMaker::timeColor() const
{
    QTime time = QTime::currentTime();
    int r = time.hour();
    int g = time.minute();
    int b = time.second();
    return QColor::fromRgb(r, g, b);
}

ColorMaker::GenerateAlgorithm ColorMaker::algorithm() const
{
    return m_algorithm;
}

void ColorMaker::setAlgorithm(GenerateAlgorithm algorithm)
{
    m_algorithm = algorithm;
}

void ColorMaker::start()
{
    if(m_nColorTimer == 0)
    {
        m_nColorTimer = startTimer(1000);
    }
}

void ColorMaker::stop()
{
    if(m_nColorTimer > 0) {
        killTimer(m_nColorTimer);
        m_nColorTimer = 0;
    }
}

void ColorMaker::timerEvent(QTimerEvent *e)
{
    if(e->timerId() == m_nColorTimer) {
        switch (m_algorithm) {
        case RandomRGB:
            m_currentColor.setRgb(qrand() % 255,
                                  qrand() % 255,
                                  qrand() % 255
                                  );
            break;
        case RandomRed:
            m_currentColor.setRed(qrand() % 255
                                  );
            break;
        case RandomGreen:
            m_currentColor.setGreen(qrand() % 255
                                  );
            break;
        case RandomBlue:
            m_currentColor.setBlue(qrand() % 255
                                  );
            break;
        case LinearIncrease:
            int r = m_currentColor.red() + 10;
            int g = m_currentColor.green() + 10;
            int b = m_currentColor.blue() + 10;
            m_currentColor.setRgb(r % 255, g % 255, b % 255);
            break;
        }
        emit colorChanged(m_currentColor);
        emit currentTime(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss"));
    }
    else {
        QObject::timerEvent(e);
    }
}

在main.cpp文件中使用qmlRegisterType函数注册C++类型
int qmlRegisterType(const char *uri, int versionMajor, int versionMinor, const char *qmlName)
This template function registers the C++ type in the QML system with the name qmlName, in the library imported from uri having the version number composed from versionMajor and versionMinor.
这个模板函数注册C++类型,在QML系统中命名为qmlname,
在从uri导入的库,该库的版本数字由versionMajor和versionMinor组成(大版本及小版本,如:1.0, 1.1, …)

main.qml文件

import QtQuick 2.7
import QtQuick.Controls 2.0
import QtQuick.Layouts 1.0
import com.superyu.ColorMaker 1.0

Rectangle {
    width: 400
    height: 400
    Text {
        id: timeLabel
        anchors.left: parent.left
        anchors.leftMargin: 5
        anchors.top: parent.top
        anchors.topMargin: 5
        font.pointSize: 26
    }
    ColorMaker {
        id: colorMaker
        color: "red"
    }
    Rectangle {
        id: colorRect
        anchors.centerIn: parent
        width: 200
        height: 200
        color: "blue"
    }
    Button {
        id: start
        text: "Start"
        anchors.left: parent.left
        anchors.leftMargin: 5
        anchors.bottom: parent.bottom
        anchors.bottomMargin: 5
        onClicked: {
            colorMaker.start();
        }
    }
    Button {
        id: stop
        text: "Stop"
        anchors.left: start.right
        anchors.leftMargin: 5
        anchors.bottom: start.bottom
        onClicked: {
            colorMaker.stop();
        }
    }

    function changeAlgorithm(button, algorithm) {
        switch(algorithm)
        {
        case 0:
            button.text = "RandomRGB";
            break;
        case 1:
            button.text = "RandomRed";
            break;
        case 2:
            button.text = "RandomGreen";
            break;
        case 3:
            button.text = "RandomBlue";
            break;
        case 4:
            button.text = "LinearIncrease";
            break;
        }
    }
    Button {
        id: colorAlgorithm
        text: "RandomRGB"
        anchors.left: stop.right
        anchors.leftMargin: 5
        anchors.bottom: start.bottom
        onClicked: {
            var algorithm = (colorMaker.algorithm() + 1) % 5;
            changeAlgorithm(colorAlgorithm, algorithm);
            colorMaker.setAlgorithm(algorithm)
        }
    }
    Button {
        id: quit
        text: "Quit"
        anchors.left: colorAlgorithm.right
        anchors.leftMargin: 5
        anchors.bottom: start.bottom
        onClicked: {
            Qt.quit();
        }
    }
    Component.onCompleted: {
        colorMaker.color = Qt.rgba(0, 180, 120, 255);
        colorMaker.setAlgorithm(colorMaker.LinearIncrease);
        changeAlgorithm(colorAlgorithm, colorMaker.algorithm());
    }

    Connections {
        target: colorMaker
        onCurrentTime: {
            timeLabel.text = timeStr;
            timeLabel.color = colorMaker.timeColor;
        }
    }
    Connections {
        target: colorMaker
        onColorChanged: {
            colorRect.color = color;
        }
    }
}

import com.superyu.ColorMaker 1.0
这个导入库在main.cpp文件的qmlRegisterType(“com.superyu.ColorMaker”, 1, 0, “ColorMaker”);定义了

使用ColorMaker对象

ColorMaker {
    id: colorMaker
    color: "red"
}

点击colorAlgorithm按钮改变颜色显示算法

Button {
    id: colorAlgorithm
    text: "RandomRGB"
    anchors.left: stop.right
    anchors.leftMargin: 5
    anchors.bottom: start.bottom
    onClicked: {
        var algorithm = (colorMaker.algorithm() + 1) % 5;
        changeAlgorithm(colorAlgorithm, algorithm);
        colorMaker.setAlgorithm(algorithm)
    }
}

在组件加载完后,再改变颜色算法

Component.onCompleted: {
    colorMaker.color = Qt.rgba(0, 180, 120, 255);
    colorMaker.setAlgorithm(colorMaker.LinearIncrease);
    changeAlgorithm(colorAlgorithm, colorMaker.algorithm());
}

连接信号到Qml

Connections {
    target: colorMaker
    onCurrentTime: {
        timeLabel.text = timeStr;
        timeLabel.color = colorMaker.timeColor;
    }
}
Connections {
    target: colorMaker
    onColorChanged: {
        colorRect.color = color;
    }
}
//colorMaker.h
signals:
    void colorChanged(const QColor &color);
    void currentTime(const QString &timeStr);

更新事件及改变colorRect的颜色

QML调用C++对象总结

1.创建一个父类为QObject的类;
2.将要曝光给QML的属性用Q_Property声明,如:Q_PROPERTY(QColor color READ getColor WRITE setColor NOTIFY colorChanged),函数用Q_INVOKABLE声明;
3.注册类型qmlRegisterType(“com.superyu.ColorMaker”, 1, 0, “ColorMaker”)
4.在qml文件中导入C++类,import com.superyu.ColorMaker 1.0
5.在qml文件中使用Connections,与C++类发送的信号相连

Connections {
    target: colorMaker  //连接对象
    onColorChanged: {   //信号槽函数
        colorRect.color = color;
    }
}

C++调用QML

例子

cppInvokeQml.qml

import QtQuick 2.0

Item {
    id: root
    width: 200
    height: 200

    //自定义属性,cpp可以访问
    property string msg: "superyu"

    //自定义信号,可以触发cpp槽函数
    signal qmlSendMsg(string arg1, string arg2)

    Rectangle {
        anchors.fill: parent
        color: "red"
        objectName: "rect"
    }

    MouseArea {
        anchors.fill: parent
        onClicked: {
            console.log("qml点击鼠标, 发送信号qmlSendMsg");
            root.qmlSendMsg(root.msg, "myarg2");
        }
    }

    onHeightChanged: console.log("qml height changed...");
    onWidthChanged: console.log("qml width changed...");

    //QML中的方法可以被cpp调用,也可以作为槽函数
    function qmlMethod(var_arg)
    {
        console.log("qml method running", var_arg, "return ok");
        return "ok";
    }

    function qmlRecvMsg(arg1, arg2)
    {
        console.log("qml slot running...", arg1, arg2);
    }
}

自定义信号和属性,以便于cpp文件中使用
cppCallQml.h文件

#ifndef CPPCALLQML_H
#define CPPCALLQML_H

#include <QObject>
#include <QDebug>

class CppCallQml : public QObject
{
    Q_OBJECT
public:
    explicit CppCallQml(QObject *parent = Q_NULLPTR);

signals:
    //信号 --用来触发qml的函数
    //注意参数为var类型,对应qml中js函数的参数类型
    void cppSendMsg(const QVariant &arg1, const QVariant &arg2);

public slots:
    void cppRecvMsg(const QString &arg1, const QString &arg2);
};

#endif // CPPCALLQML_H

cppCallQml.cpp文件

#include "cppcallqml.h"

CppCallQml::CppCallQml(QObject *parent) : QObject(parent)
{

}

void CppCallQml::cppRecvMsg(const QString &arg1, const QString &arg2)
{
    qDebug()<< "CppObject::cppRecvMsg" << arg1 << arg2;
    qDebug()<< "emit cppSendMsg";
    emit cppSendMsg(arg1, arg2);
}

main.cpp文件

//c++调用qml
QQuickView view(QUrl("qrc:/cppInvokeQmlMain.qml"));
view.show();

//获取到qml跟对象的指针
QObject *qmlObj = view.rootObject();
QQmlProperty(qmlObj, "height").write(300);
qDebug()<< "cpp get qml property height: "
        << qmlObj->property("height");
qDebug()<< "cpp get qml property msg: "
        << qmlObj->property("msg");

//通过QQuickItem设置属性
QQuickItem *item = qobject_cast<QQuickItem*>(qmlObj);
item->setWidth(300);

//查找子项
QObject *qmlRect = qmlObj->findChild<QObject*>("rect");
if(qmlRect) {
    qDebug() << "cpp get rect color: " << qmlRect->property("color");
}

//调用qml方法
QVariant val_return;
QVariant val_arg = "superyu";
//Q_RETURN_ARG(),Q_ARG()参数必须为QVariant类型
QMetaObject::invokeMethod(qmlObj,
                            "qmlMethod",
                            Q_RETURN_ARG(QVariant, val_return),
                            Q_ARG(QVariant, val_arg));
qDebug() << "QMetaObject::invokeMethod result: " << val_return;

//关联信号槽
CppCallQml cppObj;
QObject::connect(
                    qmlObj,
                    SIGNAL(qmlSendMsg(QString, QString)),
                    &cppObj,
                    SLOT(cppRecvMsg(QString, QString))
                    );
QObject::connect(
                    &cppObj,
                    SIGNAL(cppSendMsg(QVariant, QVariant)),
                    qmlObj,
                    SLOT(qmlRecvMsg(QVariant, QVariant))
                    );

return app.exec();

QML__Nokia内部培训资料(1).pdf
https://blog.csdn.net/gongjianbo1992/article/details/87965925
https://github.com/gongjianbo/MyTestCode/tree/master/Qml/CppCallQml2020

  • 3
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
QMLC++ 交互的过程一般分为以下几个步骤: 1. 定义 C++ 类并注册到 QML 中 你需要在 C++ 中定义一个类,该类封装了你想要实现的功能。同时,你需要使用 `qmlRegisterType` 函数将该类注册到 QML 中,以便在 QML 中使用该类。 例如,你可以定义一个名为 `MyClass` 的类,并将其注册到 QML 中: ```cpp class MyClass : public QObject { Q_OBJECT public: Q_INVOKABLE int myFunction(int arg) { // 实现你的功能 } }; qmlRegisterType<MyClass>("com.example", 1, 0, "MyClass"); ``` 在上面的代码中,`Q_INVOKABLE` 用于声明 `myFunction` 函数可从 QML 中调用,`qmlRegisterType` 函数用于将 `MyClass` 类注册到 QML 中。`"com.example"` 表示注册的命名空间,`1` 和 `0` 表示主版本号和次版本号,`"MyClass"` 是在 QML 中使用的类名。 2. 在 QML 中使用 C++ 类 在 QML 中使用 C++ 类时,你需要使用 `import` 语句导入该类所在的命名空间。然后,你可以通过该命名空间来访问该类。例如: ```qml import com.example 1.0 MyClass { id: myClass } Button { onClicked: { var result = myClass.myFunction(42) // 处理返回值 } } ``` 在上面的代码中,`import` 语句用于导入 `com.example` 命名空间,`MyClass` 用于创建一个 `MyClass` 实例,`id` 属性用于设置实例的标识符,`Button` 用于创建一个按钮,`onClicked` 事件处理程序中调用了 `myFunction` 函数,并处理了它的返回值。 3. 在 C++ 中访问 QML 中的对象 如果你需要从 C++ 中访问 QML 中的对象,你可以使用 `QQuickItem` 类提供的 `findChild` 函数。例如: ```cpp QQuickItem *item = qmlEngine.rootObjects().value(0)->findChild<QQuickItem*>("myItem"); if (item) { // 处理 item 对象 } ``` 在上面的代码中,`qmlEngine.rootObjects()` 函数返回 QML 引擎中所有的根对象,`value(0)` 返回第一个根对象,`findChild` 函数用于查找名为 `"myItem"` 的子对象。 以上就是 QMLC++ 交互的基本步骤。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值