C++调用QML代码

  • C++调用QML实际上就是通过 QML 对象的指针去访问QML对象的属性和方法
  • 只要获取到QML对象的指针,接下来就和普通C++代码调用一样
  • QML中的类,其实都是继承与QObject,Qt类在构建的过程中是有对象树,每个对象都有父对象和子对象,调用对应的方法就很容易获取到
  • 获取到QML对象指针后,主要是通过这几个方法 访问 QML的
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 访问 rectisShow 的属性
  • bt2 调用 rectrotateToAngle 方法,让矩形旋转
  • bt3 调用 rectbuttonClicked方法,在QML中输出日志
  • bt4 调用 rectreciveComplexType 方法,传递复杂类型给QML,其实就是一个JSON字符串,然后在QML中解析JSON字符串,获取里面的数据

3. 运行效果

运行效果
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,539评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,911评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,337评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,723评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,795评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,762评论 1 294
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,742评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,508评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,954评论 1 308
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,247评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,404评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,104评论 5 340
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,736评论 3 324
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,352评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,557评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,371评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,292评论 2 352

推荐阅读更多精彩内容

  • 2010年元月21日 今天晚上你的象棋比赛结束了,得了第三名,进中级班的梦想破灭了,但是我们不得不承认你进步很大,...
    听雨聆声阅读 177评论 0 2
  • 根据本人长时间矫情腻歪自作自受导致的心情不好的经历,总结出了治疗心情抑郁的四大绝招。 就是 早睡,早起,运动,挣钱...
    许木木NANS阅读 239评论 2 0
  • 人一出生,从呱呱坠地开始,就有高低贵贱,三牛九教:之分。有人含着金汤匙,有人含着蜜糖,有人含着草根。不同的生长土壤...
    潘公阅读 852评论 1 1