QML和C++混合编程之QML调用c++

前言

说实话,想学QML很久了,而且也发起了好几次进攻,然后就不了了之了。这次我希望我可以学会这门语言,移动端也可以耍耍了。

我是跟着书《Qt+Quick核心编程》一点点学的,书的前面章节都比较简单,就是介绍一些控件的用法、布局的使用、事件的用法等,都比较简单,唯一觉得不好的是:没有了按F1的快捷帮助,而且在写ECMAScript时,有写方法没有补全的功能,纯手打很难受。

所以就想能用自己顺手的QWidgets和QML结合起来吗?答案是肯定的,毕竟都是Qt出品,自己的东西肯定要支持。不过这里,先简单调用继承QObject的自定义类。

 

说明和使用

先说明一下QML这门语言:对ECMAScript的扩展,并融合了Qt的元对象系统。而QtWidgets也是在元对象系统的操纵下,这样的特性就使得QML很容易从C++中得到扩展,在一定的条件下,QML就可以访问QObject派生类的成员,例如信号、槽函数、枚举类型、属性、成员函数等。

上面说法太专业?那么换个思维,看下项目下的main.cpp文件,是不是对QML和c++的混合编程一点也不怀疑了?毕竟用c++语言加载的qml文件。

还有疑问是不是“在一定的条件下,QML就可以访问QObject派生类的成员,例如信号、槽函数、枚举类型、属性、成员函数等。”这句话?

“一定条件”需要两点:一是从QObject或者QObject的派生类继承,二呢,使用Q_OBJECT宏

“信号和槽函数”平时怎么写,现在就怎么写,因为它本身实现就是依赖的元对象系统的,它的实现条件就是上面的条件

“枚举类型”需要将这个枚举类型注册到元对象系统,通过宏Q_ENUMS

“属性”同样,用宏Q_PROPERTY注册,具体用法可参考亮大博客

“成员函数”需要在函数的声明前加 Q_INVOKABLE

想了想,还是附加一个.h文件,看着更直观一点:

#ifndef COLORMAKER_H
#define COLORMAKER_H

#include <QObject>
#include <QTimerEvent>
#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:
    ColorMaker(QObject* parent=0);
    ~ColorMaker();

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

    QColor color()const;
    void setColor(const QColor& color);
    QColor timeColor() const;

    Q_INVOKABLE GenerateAlgorithm algorithm() const;
    Q_INVOKABLE void setAlgorithm(GenerateAlgorithm algorithm);

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

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

protected:
    void timerEvent(QTimerEvent* event);

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

#endif // COLORMAKER_H

具体的实现方法有两种:

上面说明了C++类应该具备的一些条件,那么qml该怎么调用c++类呢,重点来喽!有两种方法:

1> c++实现一个类,qmlRegisterType注册为QML的类型,然后在qml文件以此类型创建对象。这种调用方法我是比较喜欢的,代码看着更清晰明了。(ColorMaker为我c++的类,此代码参考安总的书中代码)

main.cpp文件

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

    QGuiApplication app(argc, argv);

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

    QQuickView viewer;
    viewer.setResizeMode(QQuickView::SizeRootObjectToView);
    viewer.setSource(QUrl("qrc:///main.qml"));
    QObject::connect(viewer.engine(),&QQmlEngine::quit,&app,&QGuiApplication::quit);
    viewer.show();

    return app.exec();
}

main.qml文件 

//文件先导入c++类型
import an.qt.ColorMaker 1.0  

//以下是在Rectangle体内的创建的C++类的对象 color属性是在C++类中Q_PROPERTY注册过的属性
ColorMaker{
        id:colorMaker;
        color: Qt.green;
    }

2> 将c++类对象作为qml的属性,安总中new出的对象,我不建议new,因为还得找时机delete,这个就很麻烦了:qml又不像c++有析构函数,那么就需要在退出时删除,close事件或quit时,都要写删除操作;然后我发现close事件又要重写QQuickView 的Close事件。

此种方法将c++类对象设为属性后,在qml中直接访问,但是这就导致枚举类型(如ColorMaker::RandomRGB)无法访问了。

main.cpp文件

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

    QGuiApplication app(argc, argv);

    QQuickView viewer;
    ColorMaker colorMaker;
    viewer.setResizeMode(QQuickView::SizeRootObjectToView);

    //此处将colorMaker设为qml全局属性
    viewer.rootContext()->setContextProperty("colorMaker",&colorMaker);
    viewer.setSource(QUrl("qrc:///main.qml"));
    QObject::connect(viewer.engine(),&QQmlEngine::quit,&app,&QGuiApplication::quit);

    viewer.show();

    return app.exec();
}

qml文件

 //无需创建对象,直接使用,如此处按钮直接调用的colorMaker的开始功能  
 Button{
        id:start;
        text: "start";
        anchors.left: parent.left;
        anchors.leftMargin: 4;
        anchors.bottom: parent.bottom;
        anchors.bottomMargin: 4;
        onClicked: {
            colorMaker.start();
        }
    }

源代码我就不提供了,想要的去找安总代码,或者留言告诉我,我再上传。

结束语

要说的都已经说了,最后给自己加个油:奥利给!!

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值