QT Quick之quick与C++混合编程

这篇具有很好参考价值的文章主要介绍了QT Quick之quick与C++混合编程。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

        Qt quick能够生成非常绚丽界面,但有其局限性的,对于一些业务逻辑和复杂算法,比如低阶的网络编程如 QTcpSocket ,多线程,又如 XML 文档处理类库 QXmlStreamReader / QXmlStreamWriter 等等,在 QML 中要么不可用,要么用起来不方便,所以就有了quick和C++混合编程的需求。

原理和方法

        简单来说,混合编程就是通过Qml高效便捷的构建UI界面,而使用C ++来实现业务逻辑和复杂算法。Qt集成了QML引擎和Qt元对象系统,使得QML很容易从C ++中得到扩展,在一定的条件下,QML就可以访问QObject派生类的成员,例如信号、槽函数、枚举类型、属性、成员函数等。

要想在Qml中访问C ++对象,必然要找到一种方法在两者之间建立联系,而Qt中提供了两种在 QML 环境中使用C ++对象的方式:

  • 在C ++中实现一个类,注册到Qml环境中,Qml环境中使用该类型创建对象
  • 在C ++中构造一个对象,将这个对象设置为Qml的上下文属性,在Qml环境中直接使用该属性

两种方式之间的区别是第一种可以使C ++类在QML中作为一个数据类型,例如函数参数类型或属性类型,也可以使用其枚举类型、单例等,功能更强大。

QML可以访问的C++ 类

        先来看第一种方式,C++类要想被QML访问,首先必须满足两个条件:一是派生自QObject类或QObject类的子类,二是使用Q_OBJECT宏。QObject类是所有Qt对象的基类,作为Qt对象模型的核心,提供了信号与槽机制等很多重要特性。Q_OBJECT宏必须在private区(C++默认为private)声明,用来声明信号与槽,使用Qt元对象系统提供的内容,位置一般在语句块首行。我们还是新建一个Qt quick工程,然后我们一点一点的来看如何实现可以被QML访问的C++类。首先肯定是需要构建一个类:

QT Quick之quick与C++混合编程,C++ / QT,qt,开发语言

 QT Quick之quick与C++混合编程,C++ / QT,qt,开发语言

 文章来源地址https://www.toymoban.com/news/detail-657721.html

信号和槽

只要是信号和槽,都可以在 QML 中访问,可以把 C++ 对象的信号连接到 QML 中定义的方法上,也可以把 QML 对象的信号连接到 C++ 对象的槽上,还可以直接调用 C++ 对象的槽或信号……所以,这是最简单好用的一种途径。

在mixing.h文件中定义一个信号和一个槽函数

 

#ifndef MIXING_H
#define MIXING_H
#include <QObject>
#include <QColor>
class Mixing : public QObject
{
    Q_OBJECT
public:
    explicit Mixing(QObject *parent = nullptr);
signals:
    void colorChanged(const QColor & color);
public slots:
    void start();
};
#endif // MIXING_H

Mixing类中的信号colorChanged()和槽函数start都可以被Qml访问,但是注意槽必须被声明为public或protected,而且信号在 C++ 中使用时要用到emit关键字,但是在Qml中就是个普通的函数。我们想要实现的效果是点击鼠标,改变窗体颜色,看一下信号和槽是如何在Qml和 C++中传递的。

在mixing.cpp中声明槽函数

#include "mixing.h"
#include <QDebug>

Mixing::Mixing(QObject *parent) : QObject(parent)
{

}

void Mixing::start()
{
    qDebug() << "start";
    emit colorChanged(Qt::blue);
}

 这里传递了一个颜色到Qml中,当然,现在我们肯定还无法在qml文件中使用Mixing类,那么如何将Mixing类注册为Qml类型呢?其实有很多办法,我们这里就举一个最常规的注册类型qmlRegisterType。它比较常见的原型:

template<typename T>
int qmlRegisterType(const char *uri, int versionMajor, int versionMinor, const char *qmlName)

 

模板参数typename ,就是你要实现的 C++ 类的类名。它的第一个参数uri ,让你指定一个唯一的包名,类似Java 中的那种,一是用来避免名字冲突,二是可以把多个相关类聚合到一个包中方便引用。比如我们常写这个语句 "import QtQuick.Controls 2.3" ,其中的 "QtQuick.Controls" 就是包名 uri ,而2.3则是版本,是versionMajor和versionMinor的组合。 qmlName则是 QML中可以使用的类名。

我们通过qmlRegisterType将Mixing注册为qml类型,修改main.cpp文件

 

#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QtQml>
#include "mixing.h"

int main(int argc, char *argv[])
{
    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);

    QGuiApplication app(argc, argv);

    qmlRegisterType<Mixing>("an.qt.Mixing", 1, 0, "Mixing");

    QQmlApplicationEngine engine;
    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
    if (engine.rootObjects().isEmpty())
        return -1;

    return app.exec();
}

 

我们把Mixing类注册成为Qml类型Mixing,主版本是1,次版本是0,包名是an.qt.Mixing。注意:注册动作一定要放在 QML 上下文创建之前,否则的话,注册是没有用的。

接下来我们就可以在qml文件中导入Mixing类,并且使用它了。

import QtQuick 2.9
import QtQuick.Window 2.2
import an.qt.Mixing 1.0

Window {
    id:root
    visible: true
    width: 640
    height: 480
    title: qsTr("mixing")
    
    MouseArea{
        anchors.fill: parent
        onClicked: {
            mixing.start()
        }
    }

    Mixing{
        id: mixing
        onColorChanged: {
            root.color = color
        }
    }
}

 

Mixing这时就像Qml中一个普通的类型一样使用了,点击鼠标,调用Mixing中的start函数,输出“start”,改变窗体的颜色为蓝色。

QT Quick之quick与C++混合编程,C++ / QT,qt,开发语言

 

枚举类型

如果想要在注册的类中使用枚举类型,可以使用Q_ENUMS 宏将该枚举注册到元对象系统中。修改mixing.h文件

class Mixing : public QObject
{
    Q_OBJECT
    Q_ENUMS(BALL_COLOR)

public:
    explicit Mixing(QObject *parent = nullptr);

    enum BALL_COLOR{
        BALL_COLOR_YELLOW,
        BALL_COLOR_BLUE,
        BALL_COLOR_GREEN,
    };

signals:
    void colorChanged(const QColor & color);

public slots:
    void start(BALL_COLOR ballColor);
};

我们注册了枚举类型之后,在Qml中就可以用 ${CLASS_NAME}.${ENUM_VALUE} 的形式来访问了。看一下qml文件中的内容。主要修改的是MouseArea部分。

MouseArea{
    anchors.fill: parent
    acceptedButtons:Qt.LeftButton | Qt.RightButton;

    onClicked: {
        if(mouse.button === Qt.LeftButton)
        {
            mixing.start(Mixing.BALL_COLOR_BLUE)
        }else if(mouse.button === Qt.RightButton){
            mixing.start(Mixing.BALL_COLOR_GREEN)
        }
    }

    onDoubleClicked: {
        mixing.start(Mixing.BALL_COLOR_YELLOW)
    }
}

从上面的代码可以看出,调用枚举类型的方法形如Mixing.BALL_COLOR_BLUE,注意前面是类名哦,不是设置的id。我们这次要实现的效果是点击鼠标左键,窗口颜色变蓝;点击鼠标右键,窗口颜色变绿;双击鼠标,窗口颜色变黄。

然后将逻辑处理部分写到mixing.cpp文件。

void Mixing::start(BALL_COLOR ballColor)
{
    QColor color;
    qDebug() << "start";
    switch (ballColor) {
        case BALL_COLOR_BLUE:
            color = Qt::blue;
            break;
        case BALL_COLOR_GREEN:
            color = Qt::green;
            break;
        case BALL_COLOR_YELLOW:
            color = Qt::yellow;
            break;
    }
    emit colorChanged(color);
}

用了一个switch选择器来实现颜色的切换。效果如下:

QT Quick之quick与C++混合编程,C++ / QT,qt,开发语言

 C++ 类的属性和成员函数

        在定义一个类的成员函数时使用Q_INVOKABLE宏来修饰,但是注意的是在QML中访问的前提是public或protected成员函数,而且这个宏必须放在返回函数前面。

而定义属性则需要使用Q_PROPERTY 宏,通过它定义的属性,可以在 QML 中访问、修改,也可以在属性变化时发射特定的信号。要想使用 Q_PROPERTY 宏,定义的类必须是QObject的后裔,必须在类首使用Q_OBJECT宏。

Q_PROPERTY宏的原型:

Q_PROPERTY(type name
           (READ getFunction [WRITE setFunction] |
            MEMBER memberName [(READ getFunction | WRITE setFunction)])
           [RESET resetFunction]
           [NOTIFY notifySignal]
           [REVISION int]
           [DESIGNABLE bool]
           [SCRIPTABLE bool]
           [STORED bool]
           [USER bool]
           [CONSTANT]
           [FINAL])

属性的type、name是必需的,其它是可选项,最常用的有READ、WRITE、NOTIFY。属性的type可以是QVariant支持的任何类型,也可以是自定义类型,包括自定义类、列表类型、组属性等。另外,属性的READ、WRITE、RESET是可以被继承的,也可以是虚函数,这些特性并不常用。

  • READ:读取属性值,如果没有设置MEMBER的话,它是必需的。一般情况下,函数是个const函数,返回值类型必须是属性本身的类型或这个类型的const引用,没有参数。
  • WRITE:设置属性值,可选项。函数必须返回void,有且仅有一个参数,参数类型必须是属性本身的类型或这个类型的指针或引用。
  • NOTIFY:与属性关联的可选信号。这个信号必须在类中声明过,当属性值改变时,就可触发这个信号,可以没有参数,有参数的话只能是一个类型同属性本身类型的参数,用来记录属性改变后的值。

我们从代码中看一下如何定义,修改mixing.h文件

class Mixing : public QObject
{
    Q_OBJECT
    Q_ENUMS(BALL_COLOR)
    Q_PROPERTY(unsigned int number READ Number WRITE setNumber NOTIFY Numberchanged)


public:
    explicit Mixing(QObject *parent = nullptr);

    enum BALL_COLOR{
        BALL_COLOR_YELLOW,
        BALL_COLOR_BLUE,
        BALL_COLOR_GREEN,
    };

    unsigned int Number() const;
    void setNumber(const unsigned int &Number);

    Q_INVOKABLE void stop();

signals:
    void colorChanged(const QColor & color);
    void Numberchanged();

public slots:
    void start(BALL_COLOR ballColor);

private:
    unsigned int m_Number;
}

可以看到我们通过Q_INVOKABLE修饰了stop函数。通过Q_PROPERTY修饰了名为number的属性,number通过Number函数读得数据,通过setNumber函数写入数据,触发信号是Numberchanged函数。在cpp文件中写这几个函数的内容。

unsigned int Mixing::Number() const
{
    return m_Number;
}

void Mixing::setNumber(const unsigned int &number)
{
    if(number != m_Number)
    {
        m_Number = number;
        emit Numberchanged();
    }
}

void Mixing::stop()
{
    qDebug() << "颜色改变啦!!!";
}

接下来我们就可以在Qml中调用函数和属性了,打开界面什么都不做时,会输出number的初始值,因为没有为其初始化,所以大家返回的数据可能不一定为0。双击时,会设置number的值,这里我们设置的是10,主要就是通过setNumber来写数的。当number的值改变,会触发Numberchanged信号,发射出去。所以还需要在Qml中写一个信号处理函数,也是输出number的值,不过现在输出的就是改变之后的number了。

MouseArea{
    anchors.fill: parent
    acceptedButtons:Qt.LeftButton | Qt.RightButton;

    onClicked: {
        if(mouse.button === Qt.LeftButton)
        {
            mixing.start(Mixing.BALL_COLOR_BLUE)
        }else if(mouse.button === Qt.RightButton){
            mixing.start(Mixing.BALL_COLOR_GREEN)
        }
    }

    onDoubleClicked: {
        mixing.start(Mixing.BALL_COLOR_YELLOW)
        mixing.number = 10;
    }
}

Mixing{
    id: mixing
    onColorChanged: {
        root.color = color
        mixing.stop(color)
    }

    Component.onCompleted:
    {
        console.log("default ball number is", number)
    }

    onNumberChanged:
    {
        console.log("new ball number is", number) 
    }
}

QT Quick之quick与C++混合编程,C++ / QT,qt,开发语言

 

到了这里,关于QT Quick之quick与C++混合编程的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Qt Quick - StackView

    StackView可以与一组相互链接的信息页面一起使用。例如,电子邮件应用程序具有单独的视图,以列出最新的电子邮件,查看特定的电子邮件和列表/查看附件。当用户打开电子邮件时,电子邮件列表视图被压入栈中,当用户选择返回时,电子邮件列表视图又被弹出。 下面的代

    2023年04月17日
    浏览(86)
  • Qt Quick 3D简介

    Qt Quick 3D是Qt自带的一套3D图形系统,与传统的Qt 3D不同的是,Qt Quick 3D采用QML来进行开发。本节则对Qt Quick 3D进行一次简单的介绍。 在main.qml中设置整个场景(entire scene)。 在使用Qt Quick 3D之前,为了能够使用QtQuick3D模块中的类型,我们必须导入它: 为了绘制任何3D场景,我们需

    2024年02月13日
    浏览(34)
  • Qt Quick - 容器控件综述

    Qt Quick Controls提供了一系列类似容器的控件。 控件 功能 ApplicationWindow 支持页眉和页脚的样式顶级窗口 Container 提供容器通用功能的抽象基类型 Frame 一组逻辑控件的可视框架 GroupBox 逻辑控件组的可视框架和标题 Page 支持页眉和页脚的样式页面控件 Pane 提供与应用程序样式和主

    2023年04月26日
    浏览(40)
  • QT quick基础:组件gridview

    组件gridview与android中gridview布局效果相同。 一、下面记录qt quick该组件的使用方法。 方法一: 运行效果 方法二: 列表和代理分开。 效果图如上。 我自己的需求,点击gridview的item,修改对应item的图片,并且改变该item的字体颜色。上述代码中,Image没有点击信号,gridview也没

    2024年01月19日
    浏览(43)
  • Qt Quick系列(9)—初识画布

    🚀作者:CAccept 🎂专栏:Qt Quick 画布元素的基本思想是使用上下文2D对象( ctx )渲染路径。上下文2D对象包含必要的图形功能,而画布充当绘图画布。 在QML中, 画布元素(canvas element)充当了绘制的容器 。2D绘制对象( ctx )提供了实际绘制的方法。绘制需要在 onPaint 中完成

    2024年02月12日
    浏览(36)
  • Qt Quick基础用法+基本知识

    Qt 是一个跨平台的, 基于C++ 和 QML进行GUI开发的工具。 Qt 4.7 发布时,引入了 QML,用于移动开发,其全面支持触摸操作、流畅的动画效果等。但在 Qt 5 中,QML 已经不再局限于移动开发,也可用于开发传统的桌面程序。 相比之下,Qt Widgets 更“老”、更成熟,而 QML/Qt Quick 则更“

    2024年02月15日
    浏览(42)
  • 第53篇 Qt Quick项目详解

    前面我们一起创建了一个Qt Quick项目,并对里面的文件进行了简单的讲解,虽然这只是一个HelloWorld程序,但对于没有Qt Quick编程经验的同学来说,这个项目还是有点复杂。在这一篇中,我们将从最简单的QML文件讲起,然后逐渐丰富项目内容,帮助大家由浅及深的进行学习,进

    2024年02月12日
    浏览(36)
  • Qt Quick 3D学习:鼠标拾取物体

    (注意,开源版的 Qt Quick 3D 是狗都不用的 GPL 协议) Qt Creator 中有一个 picking 的示例,用于演示 View3D 中物体的拾取: 在示例基础上,我又加了一个简单的拖动效果,如图所示:   在使用 OpenGL 实现拾取的时候,我们可以用射线法。Qt Quick 3D 中封装了拾取操作,通过 View3D 的

    2024年02月10日
    浏览(40)
  • 【五一创作】QML、Qt Quick /Qt中绘制圆形

    有多种方法可以在 Qt Quick 中绘制圆形。以下是一些主要方法: 使用 Canvas 元素 使用 Shapes 模块: a. 使用 PathArc 和 PathLine 元素组合绘制一个完整的圆形。 b. 使用 PathEllipse 元素绘制一个椭圆形,并将其设置为圆形。 使用 Rectangle 元素绘制圆角矩形并将圆角半径设置为宽度和高

    2024年02月03日
    浏览(41)
  • QT Quick - 自定义弹出窗口

    QT Quick - 自定义弹出窗口 弹出窗口是用户界面中常用的功能之一。在qt quick中,可以使用Popup组件来轻松创建弹出窗口。Popup是类似于用户界面控件的基本类型,它可以与Window或ApplicationWindow一起使用。当需要确保弹出窗口显示在场景中的其他项之上时,建议使用ApplicationWindo

    2024年01月25日
    浏览(38)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包