QT之在QML中使用C++类和对象

QML其实是对ECMAScript的扩展,融合了Qtobject系统,它是一种新的解释性语言,QML引擎虽然由QtC++实现,但QML对象的运行环境说到底和C++对象的上下文环境是不通的,是平行的

大家好,又见面了,我是全栈君,今天给大家准备了Idea注册码。

  QML其实是对ECMAScript的扩展,融合了Qt object系统,它是一种新的解释性语言,QML引擎虽然由Qt C++实现,但QML对象的运行环境说到底和C++对象的上下文环境是不通的,是平行的两个世界,如果想在QML中访问C++对象,那么必然要找到一种途径在两个运行环境之间建立沟通的桥梁。

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

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

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

一 类的方式实现在QML中使用C++对象

1. 定义可以导出的C++类

  要想将一个类或对象导出到QML中,必须满足以下几个条件:

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

(2)使用Q_OBJECT宏

(3)Q_INVOKABLE宏

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

(4)Q_ENUMS宏

  如果要导出的类定义了想在QML中使用的枚举类型,可以使用Q_ENUM宏将该枚举注册到元对象系统中

(5)Q_PROPERTY宏

  Q_PROPERTY宏用来定义可以通过元对象系统访问的属性,通过它定义的属性,可以在QML中访问,修改,也可以在属性变化时发射特定的信号

  例子:

QT之在QML中使用C++类和对象
QT之在QML中使用C++类和对象

#ifndef COLORMAKER_H
#define COLORMAKER_H

#include <QObject>
#include <QColor>
class ColorMaker : public QObject
{
    Q_OBJECT
    Q_ENUMS(GenerateAlgorithm)
    Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged)
    Q_PROPERTY(QColor timeColor READ timeColor)
public:
    explicit ColorMaker(QObject *parent = nullptr);
    ~ColorMaker();

    enum GenerateAlgorithm
    {
        RandomRGB,
        RandomRed,
        RandomGreen,
        RandomBlue,
        LinearIcrease
    };

    QColor color() const {return m_currentColor;}
    void setColor(const QColor& color);
    QColor timeColor() const;

    Q_INVOKABLE GenerateAlgorithm alorithm() const;
    Q_INVOKABLE void serAlgorithm(GenerateAlgorithm algorithm);

signals:
    void colorChanged(const QColor& color);
    void currentTime(const QString& strTime);

public slots:
    void start();
    void stop();

protected:
    void timerEvent(QTimerEvent *e);

private:
    GenerateAlgorithm m_algorithm;
    QColor m_currentColor;
    int m_nColorTimer;
};

#endif // COLORMAKER_H

colormaker.h

QT之在QML中使用C++类和对象
QT之在QML中使用C++类和对象

#include "colormaker.h"
#include <QTime>
#include <QTimerEvent>
#include <QDebug>

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

ColorMaker::~ColorMaker()
{

}

void ColorMaker::setColor(const QColor &color)
{
    m_currentColor = color;
    emit colorChanged(color);
}

QColor ColorMaker::timeColor() const
{
    QTime time = QTime::currentTime();
    qDebug() << time.toString("yyyy-MM-dd hh:mm:ss");
    int r = time.hour();
    int g = time.minute() * 2;
    int b = time.second() * 4;
    qDebug() << r << ":"<< g << ":"<< b;
    return QColor(r,g,b);
}

ColorMaker::GenerateAlgorithm ColorMaker::alorithm() const
{
    return m_algorithm;
}

void ColorMaker::serAlgorithm(ColorMaker::GenerateAlgorithm algorithm)
{
    m_algorithm = algorithm;
}

void ColorMaker::start()
{
    qDebug() << "ColorMaker start";
    if (m_nColorTimer == 0)
    {
        m_nColorTimer = startTimer(1000);
    }
}

void ColorMaker::stop()
{
    if (m_nColorTimer > 0)
    {
        killTimer(m_nColorTimer);
        m_nColorTimer = 0;
    }
}

void ColorMaker::timerEvent(QTimerEvent *e)
{
    if (e->timerId() == m_nColorTimer)
    {
        switch (m_algorithm) {
        case RandomRGB:
            m_currentColor.setRgb(qrand()%255, qrand()%255,qrand()%255);
            break;
        case RandomRed:
            m_currentColor.setRed(qrand()%255);
            break;
        case RandomGreen:
            m_currentColor.setGreen(qrand()%255);
            break;
        case RandomBlue:
            m_currentColor.setBlue(qrand()%255);
            break;
        case LinearIcrease:
        {
            int r = m_currentColor.red() + 10;
            int g = m_currentColor.green() + 10;
            int b = m_currentColor.blue() + 10;
            m_currentColor.setRgb(r%255,g%255,b%255);
        }
            break;
        default:
            break;
        }
        emit colorChanged(m_currentColor);
        emit currentTime(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss"));
    }
    else
    {
        return QObject::timerEvent(e);
    }
}

colormaker.cpp

2. 注册QML类型

  要注册一个QML类型,有多种方法:

  qmlRegisterSingletonType()注册一个单例类型

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

  qmlRegisterTypeNotAvaliable()注册一个类型用来占位

  qmlRegisterUncreatableType()通常用来注册一个具有附加属性的附加类型,具体参考Qt SDK

 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);

  uri 指定唯一的包名

  qmlname 是QML中可以使用的类名

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

3. 在QML中导入类型

  一旦你在C++中注册好了QML类型,就可以在QML文档中引入你注册的包,然后使用注册的类型了

import an.qt.ColorMaker 1.0
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQuickView>
#include <QtQml>
#include "colormaker.h"

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

    QGuiApplication app(argc, argv);

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

    qmlRegisterType<ColorMaker>("an.qt.ColorMaker", 1, 0, "ColorMaker");
    QQuickView viewer;
    viewer.setResizeMode(QQuickView::SizeRootObjectToView);
    viewer.setSource(QUrl("qrc:///main.qml"));
    viewer.show();

    return app.exec();
}

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

  引入包后,你可以在QML中创建 C++导入类型的对象了,与QML内建类型的使用完全一样。

Rectangle
{
    width: 360;
    height: 360;

    ColorMaker
    {
        id:colorMaker;
        color:Qt.green;
    }
}

  例:

QT之在QML中使用C++类和对象
QT之在QML中使用C++类和对象

import QtQuick 2.2 import QtQuick.Window 2.2 import QtQuick.Controls 1.4 import QtQuick.Controls.Styles 1.4 import QtQuick.Dialogs 1.3 import QtQml 2.11 import an.qt.ColorMaker 1.0 Rectangle { width: 360; height: 360; Text { id: timeLabel; anchors.left: parent.left; anchors.leftMargin: 4; anchors.top : parent.top; anchors.topMargin: 4; font.pixelSize: 26; } ColorMaker { id:colorMaker; color:Qt.green; } Rectangle { id:colorRect; anchors.centerIn: parent; width: 200; height: 200; color: "blue"; } Button { id:start; text:"start"; anchors.left: parent.left; anchors.leftMargin: 4; anchors.bottom: parent.bottom; anchors.bottomMargin: 4; onClicked: { console.log("start onClicked"); colorMaker.start(); } } Button { id:stop; text:"stop"; anchors.left: start.right; anchors.leftMargin: 4; anchors.bottom: start.bottom; anchors.bottomMargin: 4; onClicked: { colorMaker.stop(); } } function changeAlgorithm(button, algorithm) { switch(algorithm) { case 0: button.text = "RandomRGB" break; case 1: button.text ="RandomRed"; break; case 2: button.text ="RandomGreen"; break; case 3: button.text ="RandomBlue"; break; case 4: button.text ="LinearIncrease"; break; } } Button { id:colorAlgorithm; text:"RandomRGB"; anchors.left:stop.right; anchors.leftMargin: 4; anchors.bottom: stop.bottom; onClicked: { var algorithm = (colorMaker.alorithm() + 1 ) % 5; changeAlgorithm(colorAlgorithm,algorithm); colorMaker.serAlgorithm(algorithm); } } Button { id:quit text:"quit" anchors.left: colorAlgorithm.right; anchors.leftMargin: 4; anchors.bottom: colorAlgorithm.bottom; onClicked: { Qt.quit(); } } Component.onCompleted: { colorMaker.color = Qt.rgba(0,180,120,255); colorMaker.serAlgorithm(colorMaker.LinearIcrease); changeAlgorithm(colorAlgorithm,colorMaker.alorithm()); } Connections { target: colorMaker; onCurrentTime: { timeLabel.text = strTime; console.log("onCurrentTime"); // timeLabel.color = colorMaker.timeColor;  } } Connections { target: colorMaker; onColorChanged: { colorRect.color = color; } } } /*Rectangle { width: 600 height: 600 Image { id: imageLabel; width: 600; height: 540; anchors.top: parent.top anchors.left: parent.left fillMode: Image.PreserveAspectFit source: "http://images.cnblogs.com/cnblogs_com/xiaobingqianrui/1185116/o_Image%201.png" } Button { id:openBtn width: 100; height: 40; text: "Open"; anchors.top:imageLabel.bottom anchors.topMargin: 10; anchors.left: parent.left anchors.leftMargin: 10; onClicked:fileDialog.open(); } Label { id:pathLabel; text: "Hello world" font.pixelSize: 22 font.italic: true color: "steelblue" anchors.top:imageLabel.bottom anchors.topMargin: 10; anchors.left: openBtn.right anchors.leftMargin: 10 } FileDialog { id:fileDialog title: "please choose a file" nameFilters: ["Image Files (*.jpg *.png *.gif)"] onAccepted: { imageLabel.source=fileDialog.fileUrl; console.log(fileDialog.fileUrl); var imageFile = new String(fileDialog.fileUrl); pathLabel.text=imageFile.slice(8); } } }*/

View Code

二 对象的方式实现在QML中使用C++对象

1. 注册属性

viewer.rootContext()->setContextProperty("colorMaker", new ColorMaker);

2. 在QML中使用关联到的C++对象的属性

  一旦调用setContextProperty()导出了属性,就可以在QML中使用了,不需要import语句

QT之在QML中使用C++类和对象
QT之在QML中使用C++类和对象

import QtQuick 2.2 import QtQuick.Window 2.2 import QtQuick.Controls 1.4 import QtQuick.Controls.Styles 1.4 import QtQuick.Dialogs 1.3 import QtQml 2.11 //import an.qt.ColorMaker 1.0  Rectangle { width: 360; height: 360; Text { id: timeLabel; anchors.left: parent.left; anchors.leftMargin: 4; anchors.top : parent.top; anchors.topMargin: 4; font.pixelSize: 26; } /* ColorMaker { id:colorMaker; color:Qt.green; }*/ Rectangle { id:colorRect; anchors.centerIn: parent; width: 200; height: 200; color: "blue"; } Button { id:start; text:"start"; anchors.left: parent.left; anchors.leftMargin: 4; anchors.bottom: parent.bottom; anchors.bottomMargin: 4; onClicked: { console.log("start onClicked"); colorMaker.start(); } } Button { id:stop; text:"stop"; anchors.left: start.right; anchors.leftMargin: 4; anchors.bottom: start.bottom; anchors.bottomMargin: 4; onClicked: { colorMaker.stop(); } } function changeAlgorithm(button, algorithm) { switch(algorithm) { case 0: button.text = "RandomRGB" break; case 1: button.text ="RandomRed"; break; case 2: button.text ="RandomGreen"; break; case 3: button.text ="RandomBlue"; break; case 4: button.text ="LinearIncrease"; break; } } Button { id:colorAlgorithm; text:"RandomRGB"; anchors.left:stop.right; anchors.leftMargin: 4; anchors.bottom: stop.bottom; onClicked: { var algorithm = (colorMaker.alorithm() + 1 ) % 5; changeAlgorithm(colorAlgorithm,algorithm); colorMaker.serAlgorithm(algorithm); } } Button { id:quit text:"quit" anchors.left: colorAlgorithm.right; anchors.leftMargin: 4; anchors.bottom: colorAlgorithm.bottom; onClicked: { Qt.quit(); } } Component.onCompleted: { colorMaker.color = Qt.rgba(0,180,120,255); //colorMaker.serAlgorithm(colorMaker.LinearIcrease); colorMaker.serAlgorithm(2); changeAlgorithm(colorAlgorithm,colorMaker.alorithm()); } Connections { target: colorMaker; onCurrentTime: { timeLabel.text = strTime; console.log("onCurrentTime"); // timeLabel.color = colorMaker.timeColor;  } } Connections { target: colorMaker; onColorChanged: { colorRect.color = color; } } }

View Code

 

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/120078.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)
blank

相关推荐

  • 异或和左移的优先级_异或链表

    异或和左移的优先级_异或链表给定一个非负整数序列 a,初始长度为 N。有 M 个操作,有以下两种操作类型:A x:添加操作,表示在序列末尾添加一个数 x,序列的长度 N 增大 1。Q l r x:询问操作,你需要找到一个位置 p,满足 l≤p≤r,使得:a[p] xor a[p+1] xor … xor a[N] xor x 最大,输出这个最大值。输入格式第一行包含两个整数 N,M,含义如问题描述所示。第二行包含 N 个非负整数,表示初始的序列 A。接下来 M 行,每行描述一个操作,格式如题面所述。输出格式每个询问操

  • jmeter做接口压力测试_jmeter接口性能测试

    jmeter做接口压力测试_jmeter接口性能测试jmeter是apache公司基于java开发的一款开源压力测试工具,体积小,功能全,使用方便,是一个比较轻量级的测试工具,使用起来非常简单。因为jmeter是java开发的,所以运行的时候必须先要安装jdk才可以。jmeter是免安装的,拿到安装包之后直接解压就可以使用,同时它在linux/windows/macos上都可以使用。  jmeter可以做接口测试和压力测试。其中接口测试的简单操作

  • 获得焦点与失去焦点事件

    获得焦点与失去焦点事件一介绍获得焦点事件(onfocus)是当某个元素获得焦点时触发事件处理程序。失去焦点事件(onblur)是当前元素失去焦点时触发事件处理程序。一般情况下,这两个事件是同时使用的。 二应用文本框获得焦点时改变背景颜色本示例是在用户选择页面中的文本框时,改变文本框的背景颜色,当选择其他文本框时,将失去焦点的文本框背景颜色恢复原始状态。 三代码

  • wireshark抓包工具详细说明及操作使用_wireshark ping抓包

    wireshark抓包工具详细说明及操作使用_wireshark ping抓包wireshark是非常流行的网络封包分析软件,功能十分强大。可以截取各种网络封包,显示网络封包的详细信息。使用wireshark的人必须了解网络协议,否则就看不懂wireshark了。为了安全考虑,wireshark只能查看封包,而不能修改封包的内容,或者发送封包。wireshark能获取HTTP,也能获取HTTPS,但是不能解密HTTPS,所以wireshark看不懂HTTPS中的

  • c# mysql executenonquery_C#-在ExecuteNonQuery上获取受影响的行「建议收藏」

    c# mysql executenonquery_C#-在ExecuteNonQuery上获取受影响的行「建议收藏」如果您运行大量ExecuteNonQuery()并一次提交所有这些,则可以通过读取“SELECTtotal_changes();”的返回值来获得连接后的总更改数。获得总更改的函数:publicstaticlongGetTotalChanges(SQLiteConnectionm_dbConnection){stringsql=”SELECTtotal_changes();”;u…

  • C++ stringstream 类的用法「建议收藏」

    C++ stringstream 类的用法「建议收藏」(转自:https://blog.csdn.net/nwpu_yike/article/details/22100615)一、类型转换——数字-&gt;字符串C++stringstream类是一种十分有用的类,特别是当我们需要在程序中使用字符串和数字数据互相转换的时候。要想在程序中使用stringstream类,我们需要在源程序文件中包含头文件include&lt;sstream&…

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号