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

  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中访问,修改,也可以在属性变化时发射特定的信号

例子:

#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

#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;
    }
}

  例:

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);
        }
    }
}*/

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

1. 注册属性

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

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

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

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

原文地址:https://www.cnblogs.com/xiaobingqianrui/p/9771519.html

时间: 2024-08-29 11:54:18

QT之在QML中使用C++类和对象的相关文章

QML中使用C++类的实现

之前用Qt写过串口的小软件.STM32 IAP工具 和 用qt写的一个简单到不能在简单的上位机 .后来接触了QML,觉得传统的那种界面太那个了,写样式也麻烦.所以很早就想过用QML来为串口上位机做界面.无奈没搞懂QML到底是如何去调用C++的.百度了一堆文章,多半是翻译官方的例子.不知所云.直到最近在csdn上看到一篇文章 Qt Quick 之 QML 与 C++ 混合编程详解 ,终于有点懂了.不过,文章似乎有点长了.博客园上面也有见过,有朋友写过类似的文章.今天,总算实现了QML访问一个自定义

Scala中包、类、对象、成员访问权限理解

本文通过下面一个程序简单分析下包.类.对象访问权限的情况: package spark {   package navigation {     private[spark] class Navigator {       protected[navigation] def useStartChar() = println("navigation")       class LegOfJourney {         private[Navigator] val distance =

学习java中对《类与对象》的认知

在学习<类与对象>章节中,我们知道了面向对象的编程语言中,类是一个独立的程序单位,是具有相同属性和方法的一组对象的集合, 在 Java 程序中,自定义类的一般格式为: class 类名 { 数据成员1 数据成员2 数据成员3 …… 成员方法1 成员方法2 } 类的说明部分由关键字 class 与类名组成,注意的是类名的命名遵循 Java 标识符的定义规则.类体是类声明中花括号所包括的全部内容,它又是由成员变量(属性)和成员方法(方法)两部分组成. 说了类,接着就是对象的剖知了,对象是把客观世界

java中的战斗机——类与对象

1. java语言的特点——面向对象编程.万物皆对象,每个对象,我们会编写一个类来描述对象的行为和属性,类是对象的描述,对象是类的实例. 2.实例化对象,在java中,new关键字用于实例化一个对象,new运算符在内存中创建一个对象并且返回对新创建的对象的一个引用. 3. this关键字.每个对象都能使用this来引用本身,如果一个类的方法需要访问该类本身的成员变量或者其他方法,就应该用this引用. 4.本章是个难点,比较的抽象,希望在以后能把他们的关系搞透彻. 5.java学习,行且益坚,再

C++中如何定义类和对象?

在C++语言中,对象的类型被称为类,类代表了某一批对象的共性和特征. 类是对象的抽象,而对象是类的具体实例.如同C中的结构体一样,我们要先定义一个结构体,再使用结构体去定义一个变量.同一个结构体可以定义出多个不同的结构体变量.我们要使用类也是如此. 类是对象的模板,如同我们在建造房屋时候的图纸,然后我们就可以利用这个图纸去建造许多个房屋.我们可以使用别人已经定义好的类.更多的时候,我们要根据需要定义自己的类. 定义类 定义结构体的方法: struct Student { char name[12

在qml中使用model给委托对象MapPolylIne的path属性赋值。

遇到两个崩溃的问题. 1.A线程中给赋值了变量 listA, 线程B中使用函数Add(QList<GeoPath> &list),由于在其函数中调用了list.at(index),所以当listA对象改变时会使得引用而来的list导致索引越界. 2. 定义clear()函数时使用  beginRemoveRows(QModelIndex(), 0, rowCount());m_datas.clear();endRemoveRows(); 程序也崩溃,原因不明. 3.MapPolylin

.编写Java应用程序。首先,定义一个Print类,它有一个方法void output(int x),如果x的值是1,在控制台打印出大写的英文字母表;如果x的值是2,在 控制台打印出小写的英文字母表。其次,再定义一个主类——TestClass,在主类 的main方法中创建Print类的对象,使用这个对象调用方法output ()来打印出大 小写英文字母表。

package com.homework.zw; //类Print部分 public class Print1 { int x; void output() { if(x==1) { for(int i =65;i<=90;i++) { char a =(char) i; System.out.print(a); } } else if(x==2) { for(int i =97;i<=122;i++) { char a =(char) i; System.out.print(a); } }

编写Java应用程序。首先,定义一个Print类,它有一个方法void output(int x),如果x的值是1,在控制台打印出大写的英文字母表;如果x的值是2,在 控制台打印出小写的英文字母表。其次,再定义一个主类——TestClass,在主类 的main方法中创建Print类的对象,使用这个对象调用方法output ()来打印出大 小写英文字母表。

package liu0917; public class Print2 { int x; void output() { if(x==1) { for(int i =65;i<=90;i++)//大写字母在char类型中的位置 { char a =(char) i; System.out.print(a); } } else if(x==2) { for(int i =97;i<=122;i++) { char a =(char) i; System.out.print(a); } } el

Qt Quick 之 QML 与 C++ 混合编程详解

Qt Quick 技术的引入,使得你能够快速构建 UI ,具有动画.各种绚丽效果的 UI 都不在话下.但它不是万能的,也有很多局限性,原来 Qt 的一些技术,比如低阶的网络编程如 QTcpSocket ,多线程,又如 XML 文档处理类库 QXmlStreamReader / QXmlStreamWriter 等等,在 QML 中要么不可用,要么用起来不方便,所以呢,很多时候我们是会基于这样的原则来混合使用 QML 和 C++: QML 构建界面, C++ 实现非界面的业务逻辑和复杂运算. 请给