IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> Qml调用C++方法初探 -> 正文阅读

[C++知识库]Qml调用C++方法初探

为什么会在QML中调用C++方法?

  • 引入Qml的一个重要目的就是UI和逻辑的解耦,我们可以把业务逻辑用C++实现,Qml只用来开发界面,这样在后续程序改版过程中,基本上可以不动逻辑只改UI
  • 比如有一些复杂的计算逻辑,我们可以通过C++来实现,这样效率来说也会更高

QML调用C++方法主要有两种方式

  • 注册法
  • 暴露法

本文主要详解Q_INVOKABLE的关键字,通过两种方法来调用C++ 方法

1.创建一个C++方法类

利用Qt的元对象,通过Q_INVOKABLE或public slots注册到元对象系统中,进而通过函数名称直接进行调用。这里先创建一个QObject的派生类,用于实现Qml中需要调用的方法

//=================================QmlControl.h=================================//
#pragma once
#include <QObject>
class QmlControl  : public QObject
{
	Q_OBJECT

public:
	QmlControl(QObject *parent=nullptr);
	~QmlControl();
//方式一
   Q_INVOKABLE void AddData(int a,int b);
   Q_INVOKABLE QString UpdateBackground();
//方式二(等价)
//public slots:
//    void AddData(int a, int b);
//    QString UpdateBackground();
};
//=================================QmlControl.cpp=================================//
#include "QmlControl.h"
#include <QDebug>
QmlControl::QmlControl(QObject *parent) : QObject(parent) {}
QmlControl::~QmlControl() {}
void QmlControl::AddData(int a, int b) {
  qDebug() << "a=" << a << "b=" << b;
  qDebug() << "a+b=" << a + b;
}
QString QmlControl::UpdateBackground() {
  return QString("http://image.nbd.com.cn/uploads/articles/images/673466/500352700_banner.jpg");
}

2.1 qmlRegisterType注册法

使用qmlRegisterType注册一个可以被Qml识别的类型并调用

  /*
  template<typename T>
  int qmlRegisterType(const char *uri, int versionMajor, int versionMinor, const
  char *qmlName) 
  uri:qml中的包名
  versionMajor:主版本号
  versionMinor:副版本号
  qmlName:qml中类型名称
  */
  qmlRegisterType<QmlControl>("test.conrtrol", 1, 0, "QmlControl");
  QQuickWidget *qml_widget = new QQuickWidget();
  qml_widget->setResizeMode(QQuickWidget::SizeRootObjectToView);
  qml_widget->setSource(QUrl("test_qml.qml"));
  qml_widget->show();
  ui.verticalLayout->addWidget(qml_widget);

关系图
在这里插入图片描述

import QtQuick 2.12
import QtQuick.Window 2.14
import QtQuick.Controls 2.14
import QtQuick.Controls.Styles 1.4
import test.conrtrol 1.0
Rectangle {
    color: "gray"
    radius:10
 	QmlControl {
       id: qmlctrl
    }
    Image {
        id:background_image
        anchors.fill: parent
        fillMode: Image.PreserveAspectCrop
        source: "http://cube.elemecdn.com/6/94/4d3ea53c084bad6931a56d5158a48jpeg.jpeg"
        antialiasing: true
    }
    Button {
        text: "Left"
        anchors.bottom: parent.bottom
        anchors.left: parent.left
        anchors.leftMargin:50
        background: Rectangle {
            color:"#0b81ff"
            implicitWidth: 100;
            implicitHeight: 50;
            radius: 6;
        }
        //信号槽连接
        onClicked: {
           	qmlctrl.AddData(99,88);
            console.log("我被点击了"+text)
        }
    }
    Button {
        text: "Right"
        anchors.bottom: parent.bottom
        anchors.right:  parent.right
        anchors.rightMargin:50
        background: Rectangle {
            color:"#0b81ff"
            implicitWidth: 100;
            implicitHeight: 50;
            radius: 6;
        }
        //信号槽连接
        onClicked: {
            background_image.source=qmlctrl.UpdateBackground();
            console.log("我被点击了"+text)
        }
    }
}

2.2 setContextProperty暴露法

通过 setContextProperty暴露给Qml,这里都是以QQuickWidget举例(Qml与QWidget混合开发)

  //注册方式二(写法1)
  //QQmlApplicationEngine *engine = new QQmlApplicationEngine();
  //engine->rootContext()->setContextProperty("qml_ctrl", &qml_control);
  //QQuickWidget *qml_widget = new QQuickWidget(engine,nullptr);
  //注册方式二(写法2)
  QQuickWidget *qml_widget = new QQuickWidget();
  qml_widget->rootContext()->setContextProperty("qml_ctrl", &qml_control);

  qml_widget->setResizeMode(QQuickWidget::SizeRootObjectToView);
  qml_widget->setSource(QUrl("test_qml.qml"));
  qml_widget->show();
  ui.verticalLayout->addWidget(qml_widget);

这种暴露的方式,无需要引入包名,并且在外部定义了C++类,调用C++方法为

 > 注册名.function()
 //qml_ctrl.UpdateBackground();
 //qml_ctrl.AddData(99,88);

关系图
在这里插入图片描述

暴露法和注册法区别

  • setContextProperty 的暴露法C++类实列化一次,可能同时被多个qml共享,C++类需要我们来维护生命周期,要自己手动释放。在QQuickWidget控件中,如果不同的QQuickWidget共享了同一个QQmlApplicationEngine,则这个QQmlApplicationEngine下暴露的C++类是共享的。
  • qmlRegisterType 则是每个文件qml中创建由C++导出的类型,实例后使用,全局不唯一。
  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-07-05 23:22:06  更:2022-07-05 23:23:25 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/11 19:44:01-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码