zoukankan      html  css  js  c++  java
  • 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
    {
         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
    {
         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;
             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
    {
         600
        height: 600
    
        Image {
            id: imageLabel;
             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
             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语句

    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
    {
         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;
             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
  • 相关阅读:
    类的加载过程
    算法模板之基数排序
    算法模板之Dijkstra
    算法模板之SPFA
    算法模板之树状数组
    算法模板之排序
    深入JVM-自动内存管理(读书笔记)
    VMware Fault-Tolerant Virtual Machine 论文总结
    深入JVM--高效并发(读书笔记)
    欧拉素数筛
  • 原文地址:https://www.cnblogs.com/xiaobingqianrui/p/9771519.html
Copyright © 2011-2022 走看看