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

quick 2 — qml 与c++的混合编程

        Qt Quick 技术的引入,能够快速流畅的构建用户界面,动画、绚丽的都不在话下。但他不是万能的。也有很多局限性,原来的qt技术,比如低阶的网络编程如QTcpSocket、多线程,又比如XML文档处理类库QXMLStreamReader、QXMLStreamWriter,再如文件操作QFile等,在QML中使用并不方便。因此,基于这种情况就需要混合使用QML和C++:使用QML构建界面,C++实现非界面的业务逻辑和复杂运算。

1. 在QML中使用C++类的对象

Qt提供了两种在QML中使用C++对象的方式:

(1)在C++中实现一个类,注册为QML环境的一个类型,在QML环境中使用该类型创建对象;

(2)在C++中构造一个对象,将这个对象设置为QML的上下文属性,在QML环境中直接使用该属性。

1.1 方法一:C++类注册QML类型

1.1.1 定义可以导出的C++类

满足2个前提:

(1)从QObjec或QObject的派生类继承;

(2)使用Q_OBJECT宏;

        这两个条件是为了让一个类进入Qt的元对象系统,只有使用元对象系统,类的某些方法才可能通过字符串形式的名字调用,才能在QML中被访问。

1.1.1.1 信号、槽

        只要是信号、槽,都可以在QML中被访问,可以把C++对象的信号连接到QML中定义的方法上,也可以吧QML对象的信号连接到C++对象的槽上,还可以直接调用C++对象的槽或信号。在定义类的成员函数时使用 Q_INVOKABLE 宏来修饰,就可以让该方法被元对象系统调用。这个类型必须在返回类型前面。

1.1.1.2 Q_INVOKABLE 宏

        在定义类的成员函数时使用 Q_INVOKABLE 宏来修饰,就可以让该方法被元对象系统调用。这个类型必须在返回类型前面。

        使用Q_INVOKABLE 将方法注册到元对象系统中,在QMl中就能调用${Object}.${method}来访问了,在main.qml中使用 getAlgorithm() 和 setAlgorithm() 的QML代码:

...................................

1.1.1.3 Q_ENUMS 宏

如果导出类定义的枚举变量,可以使用Q_ENUM宏将该枚举类型注册到元对象系统中:

        使用Q_ENUM注册之后,在QML中就可以使用${CLASS_NAME}.${ENUM_VALUE}的形式来访问了。

1.1.1.4 Q_PROPERTY 宏

        Q_PROPERTY 宏用来定义可通过元对象系统访问属性,通过它定义的属性,可以在QML中访问、修改,也可以在属性变化时发射特定的信号。常用的是READ、WRITE、NOTIFY三个选项。

(1)READ 标记:如果没有置顶MEMBER标记,则READ必不可少;声明一个读取属性的函数,该函数一般没有参数,返回定义的属性。

(2)WRITE 标记:可选配置。声明一个设定属性的函数。它指定的函数没有返回值,只能有一个与属性类型匹配的参数。

(3)NOTIFY 标记:可选配置。给属性关联一个信号(该信号必须是已经在类中声明过的),当属性的值发生变化时就会触发信号。信号的参数,一般就是你定义的属性。

1.1.2 注册一个QML可用的类型

需要4步:

(1)实现C++类;

(2)注册QML类型;

(3)在QML中导入类型;

(4)在QML中创建由C++导出的类型的实例并使用。

1.1.2.1 注册QML类型

注册QML类型,有多种方法可以调用:(这里说明几种常规类型,其他参考Qt SDK)

(1)qmlRegisterSingletonType() 用来注册一个单例类型

(2)qmlRegisterType() 用来注册一个非单例类型

(3)qmlRegisterTypeNotAvailable() 注册一个类型占位

(4)qmlRegisterUncreatableType()通常用来注册一个具有附加属性的附加类型

其中 qmlRegisterType() 是个模版函数,有两个原型:

template<typename T>

int qmlRegisterType(const char *uri, int versionMajor, int versionMinor, const char *qmlName);

template<typename T, int metaObjectRevision>

int qmlRegisterType(const char *uri, int versionMajor, int versionMinor, const char *qmlName);

前一个原型一般是用来注册一个新类型,而后一个可以为特定的版本注册类型。例如:

1.1.2.2 在QML中导入C++注册的类型

在qml中引入注册的包,然后就可以使用注册类型了。(引入包,使用import语句)

import an.qt.ColorMaker 1.0
 1.2.2.3 在QML中创建C++导入类型的实例

1.1.3 代码示例

1.1.3.1 c++ 类 ColorMaker.h
#ifndef COLORMAKER_H
#define COLORMAKER_H

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

class ColorMaker : public QObject
{
    Q_OBJECT
    Q_ENUMS(EmAlgorithm);
    Q_PROPERTY(QColor color READ getColor WRITE setColor NOTIFY sigColorChanged)
    Q_PROPERTY(QColor timeColor READ timeColor)
public:
    enum EmAlgorithm{EmRandomRGB, EmRandomRed, EmRandomGreen, EmRandomBlue, EmLinearIncrease};
    explicit ColorMaker(QObject *parent = nullptr);
    ~ColorMaker();
    QColor getColor() const;
    void setColor(const QColor &color);
    QColor timeColor() const;
    Q_INVOKABLE EmAlgorithm getAlgorithm() const;
    Q_INVOKABLE void setAlgorithm(EmAlgorithm algorithm);
signals:
    void sigColorChanged(const QColor &color);
    void sigCurrentTime(const QString &strTime);
public slots:
    void slotSart();
    void slotStop();
protected:
    void timerEvent(QTimerEvent *e);
private:
    EmAlgorithm m_algorithm;
    QColor m_currColor;
    int m_nColorTimer;
};

#endif // COLORMAKER_H
1.1.3.2 c++ 类 ColorMaker.cpp
#include "ColorMaker.h"
#include <QTime>
#include <QDebug>

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

ColorMaker::~ColorMaker()
{

}

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

void ColorMaker::setColor(const QColor &color)
{
    m_currColor = color;
    emit sigColorChanged(m_currColor);
}

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

ColorMaker::EmAlgorithm ColorMaker::getAlgorithm() const
{
    return m_algorithm;
}

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

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

void ColorMaker::slotStop()
{
    if(m_nColorTimer > 0)
    {
        killTimer(m_nColorTimer);
        m_nColor

http://www.kler.cn/a/404151.html

相关文章:

  • vue3+elementui-plus el-dialog全局配置点击空白处不关闭弹窗
  • 【Swift】字符串和字符
  • nginx 配置lua执行shell脚本
  • Makefile 之 自动化变量
  • 后仿真中的SDF语法之关键字 IOPATH 用法详解
  • 简单工厂模式、方法工厂模式
  • 熟悉的 Docker,陌生的 Podman
  • undefined 和 null 区别?
  • Linux 系统下的硬件视频加速
  • MyBatis实践:提高持久化层数据处理效率
  • 1、HCIP之RSTP协议与STP相关安全配置
  • Android App获取自己的公网IP地址
  • Elasticsearch面试内容整理-实践与应用场景
  • ComfyUI绘画|Stable Diffusion原理的简易讲解
  • 2024年亚太地区数学建模C题完整思路
  • “闲置经济”成新消费趋势,万物新生长期成长性如何?
  • 早期超大规模语言模型的尝试——BLOOM模型论文解读,附使用MindSpore和MindNLP的模型和实验复现
  • B树的简单实现
  • DAY4 网络编程(广播和多线程并发)
  • shell(6)之for循环
  • React可以做全栈开发吗
  • atob()为啥明明表示base64toASCII却叫atob?(2)
  • AIX下crs-5005 ip address is aready in use in the network的解决办法
  • Apple Vision Pro开发003-PolySpatial2.0新建项目
  • Ubuntu24.04——软件包系统已损坏
  • 关于学习小波分析