qml和c++交互经典

qml调用c++

  • 一个类或对象导出到 QML 中,必须满足 1.从 QObject 或 QObject 的派生类继承 2. 使用 Q_OBJECT 宏

  • 只要是信号或者槽,都可以在 QML 中访问

  • 定义一个类的成员函数时使用 Q_INVOKABLE 宏来修饰,就可以让该方法被元对象系统调用

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

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

注册C++类为QML类型

  • qmlRegisterInterface() :

  • qmlRegisterRevision() :

  • qmlRegisterSingletonType() :

  • qmlRegisterType() : 注册可实例化的对象类型

  • qmlRegisterTypeNotAvailable() :

  • qmlRegisterUncreatableType() :注册不可被实例化的具有名称的C++类型,但是这样的类型依然可以作为QML类型系统可识别的一种类型。如果该类型的枚举或者附加特性需要在QML中使用,但是类型本身不应被实例化,就需要使用这种方式进行注册

常用的为qmlRegisterType(),它有三个重载函数,这里只介绍其一:

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

uri是需要导入到QML中的库名,versionMajor和versionMinor是其版本数字,qmlName是在QML中可以使用的类型名。

qmlRegisterType<Gemini>("Union.Lotto.Gemini", 1, 0, "Gemini");  

Gemini类注册到Qt元对象系统后,Gemini类中的信号和槽就可以在qml中调用。

注:注意:第四个QML的类名首字母一定要大写,要不然会报错。。而且是那种你找不到的。。

qml使用c++中的枚举

要想在QML中使用,就用到了Q_ENUMS()宏。

c++:

Q_ENUMS(BALL_COLOR)  

enum BALL_COLOR {  
    BALL_COLOR_YELLOW,  
    BALL_COLOR_RED,  
    BALL_COLOR_BLUE,  
    BALL_COLOR_ALL  
};  

qml:

onBegin: doSomething(Gemini.BALL_COLOR_RED)  

在QML中使用枚举类型的方式是<CLASS_NAME>.<ENUM_VALUE>

qml调用C++成员函数

在QML中访问的前提是public或protected成员函数,且使用Q_INVOKABLE宏,位置在函数返回类型的前面。

c++:

Q_INVOKABLE void stop() {  
    qDebug() << "Gemini::stop() called";  
}  

qml:

 gemini.stop()

在QML中访问C++的成员函数的形式是<id>.<method>

qml调用C++类的属性

了Q_PROPERTY()宏,用来在QObject派生类中声明属性,这个属性如同类的数据成员一样,但它又有一些额外的特性可通过Qt元对象系统来访问。

Q_PROPERTY()(type name  
  (READ getFunction [WRITE setFunction] |  
             MEMBER memberName [(READ getFunction | WRITE setFunction)])  
            [RESET resetFunction]  
            [NOTIFY notifySignal]  
            [REVISION int]  
            [DESIGNABLE bool]  
            [SCRIPTABLE bool]  
            [STORED bool]  
            [USER bool]  
            [CONSTANT]  
            [FINAL])  

type、name是必需的,其它是可选项,其它是可选项,常用的有READ、WRITE、NOTIFY。
属性的type可以是QVariant支持的任何类型,也可以是自定义类型。
READ:读取属性值,如果没有设置MEMBER的话,它是必需的。一般情况下,函数是个const函数,返回值类型必须是属性本身的类型或这个类型的const引用,没有参数。
WRITE:设置属性值,可选项。函数必须返回void,有且仅有一个参数,参数类型必须是属性本身的类型或这个类型的指针或引用。
NOTIFY:与属性关联的可选信号。这个信号必须在类中声明过,当属性值改变时,就可触发这个信号,可以没有参数,有参数的话只能是一个类型同属性本身类型的参数,用来记录属性改变后的值。

c++:

Q_PROPERTY(unsigned int ballNumber READ ballNumber WRITE setBallNumber NOTIFY ballNumberChanged)

qml:

gemini.ballNumber = 10 

注册c++对象

在C应用程序加载QML对象时,我们可以直接嵌入一些C数据来给QML使用,这里需要用到QQmlContext::setContextProperty()

c++:

app_ctrl = AppCtrl::getInstance();//new一个实例

QQmlApplicationEngine engine;

engine.rootContext()->setContextProperty("gAppCtrl", app_ctrl );//将实例添加进qml

qml:

QtObject
{
    id: idRootPriv;
    property var m_vm : null;
}

// event and signals handler事件和信号处理程序
Component.onCompleted:
{
	console.debug("Window onCompleted.");//在完成窗口
	idRootPriv.m_vm = gAppCtrl.allocViewModel("");
}

实例

#ifndef STRINGT_H
#define STRINGT_H

#include <QObject>

class stringt : public QObject
{
    Q_OBJECT
    //使用宏Q_PROPERTY可以让方法被moc感知
    Q_PROPERTY(QString Ttext READ Ttext WRITE setTtext)
public:
    explicit stringt(QObject *parent = 0);
    ~stringt();

    QString Ttext(void) const;
    Q_INVOKABLE void setTtext(const QString str);
signals:

public slots:

private:
    QString m_String;
};

#endif // STRINGT_H
#include "stringt.h"

stringt::stringt(QObject *parent)
    : QObject(parent)
    , m_String("Text just")
{
}

stringt::~stringt()
{
}

QString stringt::Ttext() const
{
    return m_String;
}

void stringt::setTtext(const QString str)
{
    m_String = str;
}
接着就是main文件里面,注册这个类就可以了,用qmlRegisterType这个函数

#include <QApplication>
#include <QQmlApplicationEngine>
#include <QtQml>
#include "stringt.h"

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);

    qmlRegisterType<stringt>("m.stringT", 1, 0, "StringT");
                   //要导入的类  包名 主版本号 次版本号 元素名
    QQmlApplicationEngine engine;
    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));

    return app.exec();
}
在qml中导入使用

import QtQuick 2.4
import QtQuick.Controls 1.3
import QtQuick.Window 2.2
import QtQuick.Dialogs 1.2
import m.stringT 1.0    //导入类

ApplicationWindow {
    title: qsTr("Hello World")
    width: 640
    height: 480
    visible: true

    StringT{    //创建一个元素
        id: stringT
    }

    Rectangle {
        id: rect1
        x: 12; y: 12
        width: 60; height: 60
        color: "lightsteelblue"
        MouseArea {
            id: rect1_area
            anchors.fill: parent
            onClicked:
            {
                rect2.color = "lightgreen"
                stringT.setTtext(rect1_text.text)
                rect2_text.text = stringT.Ttext
            }
        }
    }

    Rectangle {
        id: rect2
        x: rect1.x + rect1.width + 10
        y: rect1.y
        width: rect1.width; height: rect1.height
        border.color: "lightsteelblue"
        border.width: 3
        radius: 3
        Text {
            id: rect2_text
            text: qsTr("Hello")
            font.pixelSize: 12
            anchors.centerIn: parent
        }
    }
}

c++调用qml

在C++中,使用QMetaObject::invokeMethod()可以调用QML中的函数。

static bool invokeMethod(QObject *obj, const char *member, Qt::ConnectionType, QGenericReturnArgument ret, QGenericArgument val0 = QGenericArgument(Q_NULLPTR), ...... //后面还有9个参数


QGenericArgument           Q_ARG(Type, const Type & value)  
QGenericReturnArgument     Q_RETURN_ARG(Type, Type & value)

c++:

QMetaObject::invokeMethod(object, "qmlFunction",  
                          Q_RETURN_ARG(QVariant, returnedValue),  
                          Q_ARG(QVariant, message));
# qml  

评论

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×