QT开发中文网

C++调用QML代码

  • C++调用QML实际上就是通过 QML 对象的指针去访问QML对象的属性和方法

  • 只要获取到QML对象的指针,接下来就和普通C++代码调用一样

  • QML中的类,其实都是继承与QObject,Qt类在构建的过程中是有对象树,每个对象都有父对象和子对象,调用对应的方法就很容易获取到

  • 获取到QML对象指针后,主要是通过这几个方法 访问 QML的

QT开发交流+赀料君羊:661714027

QT开发交流+赀料君羊:661714027

QVariant QObject::property(const char *name) const  // 访问变量
bool QObject::setProperty(const char *name, const QVariant &value)  // 设置变量的值
QMetaObject::invokeMethod  // 调用方法

1.QML 代码

import QtQuick 2.0
import QtQuick.Window 2.2

Rectangle {
    width: 500
    height: 400

    // 测试传数组
    ListView {
        id: listView

        model : ListModel {
            id: myModel
        }

        width: 100
        height: 400

        delegate: Rectangle{
            height: 20
            width: 100
            color : "#9bee95"

            Text {
                anchors.centerIn: parent
                horizontalAlignment: Text.AlignHCenter
                text: val   //访问model 中的数据
            }
        }
    }

    Rectangle {
        id : rect
        objectName: "rect"

        anchors.centerIn: parent
        width: 100
        height: 100
        color: "#00ffffff"
        border.color: "#19e8d0"
        border.width: 5
        radius: 10

        // 定义一个变量,让C++访问
        property bool isShow: visible

        // 定义一个方法,让C++调用
        function rotateToAngle(angle) {
            rotation = angle
            return true
        }

        function buttonClicked(){
            console.log("按钮被点击")
        }

        // 接收复杂类型
        function reciveComplexType( comp ) {
            var obj = JSON.parse(comp)

            console.log(obj.name)
            console.log(obj.val)

            myModel.clear();
            for (var i=0; i < obj.arr.length; ++i)
                myModel.append({"val" : obj.arr[i] })

        }

        Text {
            id: text
            objectName: "text"
            text : "C++调用QML";

            anchors.centerIn: parent
        }
    }
}
  • C++要调用的对象要设置objectName,否则无法获取到QML对象的指针
  • property bool isShow: visible C++中访问 isShow 变量
  • function rotateToAngle(angle) C++中调用 rotateToAngle 方法,传一个float类型
  • function buttonClicked() C++中调用 buttonClicked 方法
  • function reciveComplexType( comp ) C++中传递一个json字符串过来,QML中解析json数据

2. C++/Qt 代码

  • 主函数代码
int main(int argc, char **argv)
{
  QApplication a(argc, argv);

  // 显示QML界面
  QQuickView view;
  view.setSource(QUrl::fromLocalFile( "../Cpp_Call_QML/main.qml"));
  view.show();

  // 初始化QML根节点
  QMLObj::instance().initQMLRootObj(view.rootObject());

  // 模拟C++调用QML
  Cpp c;
  c.show();

  return a.exec();
}
  • 这里调用 QMLObj::instance().initQMLRootObj(view.rootObject()); 将QML的根元素存了起来,为了找他的子对象

QMLObj类代码

#pragma once

#include <QHash>
#include <QObject>
#include <QQuickItem>

class QMLObj
{
  QMLObj() : rootItem(nullptr) {}
public:
  static QMLObj &instance()
  {
      static QMLObj obj;
      return obj;
  }

  void initQMLRootObj(QObject * rootItem)
  {
      this->rootItem = rootItem;
  }

  QObject * getQMLObject(const QString objName)
  {
      if (qmlObjs.find(objName) != qmlObjs.end())
      {
          return qmlObjs[objName];
      }
      else if (rootItem)
      {
          QObject *obj = rootItem->findChild<QObject *>(objName);
          if (!obj) return nullptr;
          qmlObjs[objName] = obj;
          return obj;
      }
      else
      {
          return nullptr;
      }
  }


private:
  QHash<QString, QObject *> qmlObjs;

  QObject *rootItem;
};

这个类就是为了获取QML对象的指针,只要拿到指针就好办了

因为不知道怎么获取QML全局的root对象,所以就从main函数中把rootObject传给这个类做初始化,QML不像QApplication,QApplication可以直接调用静态方法 instance() 获取实例。

C++调用代码

#include "Cpp.h"
#include <QPushButton>
#include <QDebug>
#include <QApplication>
#include <QQmlApplicationEngine>
#include <QMetaObject>
#include <QJsonObject>
#include <QJsonDocument>
#include <QJsonArray>
#include <QHBoxLayout>
#include "QMLObj.h"

Cpp::Cpp(QWidget *parent) : QWidget(parent)
{
  QPushButton * bt1 = new QPushButton("访问isShow", this);
  QPushButton * bt2 = new QPushButton("调用 rotateToAngle", this);
  QPushButton * bt3 = new QPushButton("调用 buttonClicked", this);
  QPushButton * bt4 = new QPushButton("调用 reciveComplexType", this);

  QHBoxLayout * layout = new QHBoxLayout;
  this->setLayout(layout);

  layout->addWidget(bt1);
  layout->addWidget(bt2);
  layout->addWidget(bt3);
  layout->addWidget(bt4);

  connect(bt1, &QPushButton::clicked, []{
      QObject *rect = QMLObj::instance().getQMLObject("rect");
      if (rect)
      {
          qDebug() << rect->property("isShow").toBool();          
      }
  } );


  connect(bt2, &QPushButton::clicked, []{
      QObject *rect = QMLObj::instance().getQMLObject("rect");
      if (rect)
      {
          QVariant ok = false;
          QMetaObject::invokeMethod(rect, "rotateToAngle", Q_RETURN_ARG(QVariant, ok), Q_ARG(QVariant, 60));
      }
  });

  connect(bt3, &QPushButton::clicked, [] {
      QObject *rect = QMLObj::instance().getQMLObject("rect");
      if (rect)
      {
          QMetaObject::invokeMethod(rect, "buttonClicked");
      }
  });

  connect(bt4, &QPushButton::clicked, []{
      QObject *rect = QMLObj::instance().getQMLObject("rect");
      if (rect)
      {
          //  复杂数据类型
          QJsonObject jsObj;

          jsObj["name"] = "复杂数据类型";
          jsObj["val"] = 12345;

          QJsonArray arr;
          arr.append("复");
          arr.append("杂");
          arr.append("数");
          arr.append("据");

          jsObj["arr"] = arr;

          QMetaObject::invokeMethod(rect, "reciveComplexType", Q_ARG(QVariant, QJsonDocument(jsObj).toJson()));
      }
  });
}

bt1 访问 rect 的 isShow 的属性

bt2 调用 rect 的 rotateToAngle 方法,让矩形旋转

bt3 调用 rect 的 buttonClicked方法,在QML中输出日志

bt4 调用 rect 的 reciveComplexType 方法,传递复杂类型给QML,其实就是一个JSON字符串,然后在QML中解析JSON字符串,获取里面的数据

3. 运行效果

原文作者:亿速云
原文地址:https://www.jianshu.com/p/3fac2b1d33af

目录导航
  • 1.QML 代码
  • 2. C++/Qt 代码
  • 3. 运行效果
  • 本站部分文章来源于网络,版权归原作者所有,如有侵权请联系站长删除。
    转载请注明出处:https://qt.0voice.com/?id=1823

    分享:
    扫描分享到社交APP
    上一篇
    下一篇
    发表列表
    游客 游客
    此处应有掌声~
    评论列表

    还没有评论,快来说点什么吧~

    联系我们

    在线咨询: 点击这里给我发消息

    微信号:3007537140

    上班时间: 10:30-22:30

    关注我们
    x

    注册

    已经有帐号?