QML与C++通信

一、QML中如何使用C++的类和对象

前提条件:
1.从 QObject 或 QObject 的派生类继承
2.使用 Q_OBJECT 宏
这两个条件是为了让一个类能够进入 Qt 强大的元对象系统(meta-object system)中,只有使用元对象系统,一个类的某些方法或属性才可能通过字符串形式的名字来调用,才具有了在 QML 中访问的基础条件。
一旦导出了一个类,在 QML 中就必然要访问该类的实例的属性或方法来达到某种目的,而具有什么特征的属性或方法才可以被 QML 访问呢?

信号和槽(针对C++中类的函数而言)
class ColorMaker : public QObject
{
    Q_OBJECT
 
public:
    ColorMaker(QObject *parent = 0);
    ~ColorMaker();
    
signals:
    void colorChanged(const QColor & color);
    void currentTime(const QString &strTime);
 
public slots:
    void start();
    void stop();
    
};

我们定义了 start() / stop() 两个槽, colorChanged() / currentTime() 两个信号,都可以在 QML 中通过对象的方法直接使用,例如:

ColorMaker{
	id:colormaker
}
colormaker.start();或者colormaker.colorChanged(color);
使用Q_INVOKABLE 宏修饰的普通函数(针对C++中类的函数而言)

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

class ColorMaker : public QObject
{
    Q_OBJECT
 
public:
    ColorMaker(QObject *parent = 0);
    ~ColorMaker();
    
    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();
};

algorithm()和setAlgorithm(GenerateAlgorithm algorithm)都可以在在 QML 中通过对象的方法直接使用,例如:

ColorMaker{
	id:colormaker
}
colormaker.algorithm();
使用Q_ENUMS 宏修饰的枚举类型(针对C++中类的枚举类型而言)
class ColorMaker : public QObject
{
    Q_OBJECT
    Q_ENUMS(GenerateAlgorithm)
public:
    ColorMaker(QObject *parent = 0);
    ~ColorMaker();
    
    enum GenerateAlgorithm{
        RandomRGB,
        RandomRed,
        RandomGreen,
        RandomBlue,
        LinearIncrease
    };
    
    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();
};

QML中可通过ColorMaker.LinearIncrease直接使用。

使用Q_PROPERTY 宏修饰的变量类型(针对C++中类的变量而言)
class QQuickText : public QQuickImplicitSizeItem
{
    Q_OBJECT
    Q_ENUMS(HAlignment)
    Q_PROPERTY(QString text READ text WRITE setText NOTIFY textChanged)
    Q_PROPERTY(QFont font READ font WRITE setFont NOTIFY fontChanged)
    Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged)
    ...  
public:
    ...
};

综合运用上述方法和属性:

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 *e);
 
private:
    GenerateAlgorithm m_algorithm;
    QColor m_currentColor;
    int m_nColorTimer;
};

(一)QML中使用C++中的类

方法:在 C++ 中实现一个类,注册到 QML 环境中, QML 环境中使用该类型创建对象

要注册一个 QML 类型,有多种方法可用,如 qmlRegisterSingletonType() 用来注册一个单例类型, qmlRegisterType() 注册一个非单例的类型, qmlRegisterTypeNotAvailable() 注册一个类型用来占位, qmlRegisterUncreatableType() 通常用来注册一个具有附加属性的附加类型
qmlRegisterType() 是个模板函数

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

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

#include <QtGui/QGuiApplication>
#include "qtquick2applicationviewer.h"
#include <QtQml>
#include "colorMaker.h"
 
 
int main(int argc, char *argv[])
{
    QGuiApplication app(argc, argv);
    qmlRegisterType<ColorMaker>("an.qt.ColorMaker", 1, 0, "ColorMaker");
 
    QtQuick2ApplicationViewer viewer;
    viewer.setMainQmlFile(QStringLiteral("qml/colorMaker/main.qml"));
    viewer.showExpanded();
 
    return app.exec();
}

上面的代码将 ColorMaker 类注册为 QML 类 ColorMaker ,主版本为 1 ,次版本为 0 ,而我起的包名则是 an.qt.ColorMaker 。注册动作一定要放在 QML 上下文创建之前。

QML中使用此类的方法:

import an.qt.ColorMaker 1.0
Rectangle {
    width: 360;
    height: 360;
    
    ColorMaker {
        id: colorMaker;
        color: Qt.green;
    }
}

(二)QML中使用C++中的对象

方法:在 C++ 中构造一个对象,将这个对象设置为 QML 的上下文属性,在 QML 环境中直接使用该属性
可以把 C++ 中创建的对象作为属性传递到 QML 环境中,然后在 QML 环境中访问。
main.cpp:

 QQmlContext *context = engine.rootContext();
 context->setContextProperty("myobject", myobject);

还有一点要说明,因为去掉了 qmlRegisterType() 调用,所以在 main.qml 中不能再访问 ColorMaker 类了,比如你不能通过类名来引用它定义的 GenerateAlgorithm 枚举类。
此种方法QML中无需import导入,可以直接使用myobject对象访问其属性和方法,例如myobject.iValue

二、C++中使用QML中的函数

QML 对象对应的类型,原本就是 C++ 类型,比如 Image 对应 QQuickImage , Text 对应 QQuickText……但是,这些与 QML 类型对应的 C++ 类型都是私有的,你写的 C++ 代码也不能直接访问。肿么办?
Qt 最核心的一个基础特性,就是元对象系统,通过元对象系统,你可以查询 QObject 的某个派生类的类名、有哪些信号、槽、属性、可调用方法等等信息,然后也可以使用 QMetaObject::invokeMethod() 调用 QObject 的某个注册到元对象系统中的方法。而对于使用 Q_PROPERTY 定义的属性,可以使用 QObject 的 property() 方法访问属性,如果该属性定义了 WRITE 方法,还可以使用 setProperty() 修改属性。所以只要我们找到 QML 环境中的某个对象,就可以通过元对象系统来访问它的属性、信号、槽等。

 engine.load(url);

    auto list = engine.rootObjects();
    auto window = list.first();
    //auto name = window->objectName();//
    QObject* obj =  window->findChild<QObject*>("myobjects");//myobjects为某个控件的objectname
    qDebug() << obj;
    QVariant res;
    QVariant arg = 15;
    QMetaObject::invokeMethod(obj, "func", Q_RETURN_ARG(QVariant, res),
                              Q_ARG(QVariant,arg));
    qDebug() << res;
    return app.exec();

参考文章:http://blog.csdn.net/foruok
在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值