QGenericArgument Q_ARG(Type, const Type & value)
QGenericReturnArgument Q_RETURN_ARG(Type, Type & value)
使用QObject::connect()可以连接QML中的信号,connect()共有四个重载函数,它们都是静态函数。必须使用SIGNAL()宏来声明信号,SLOT()宏声明槽函数。
使用QObject::disconnect()可以解除信号与槽函数的连接。
(1)修改main.qml
import QtQuick 2.2
import QtQuick.Window 2.1
import Union.Lotto.Gemini 1.0
Window {
visible: true
width: 360; height: 360
title: "Union Lotto Game"
color: "white"
signal qmlSignal(string message)
onQmlSignal: console.log("qml signal message is", message) // this is a qml signal
function qmlFunction(parameter) {
console.log("qml function parameter is", parameter) // Hello from C++
return "function from qml"
}
Rectangle {
objectName: "rect"
anchors.fill: parent
color: "yellow"
}
MouseArea {
anchors.fill: parent
onClicked: {
gemini.begin()
gemini.stop()
gemini.ballNumber = 10
qmlSignal("this is a qml signal")
}
}
Gemini {
id: gemini
onBegin: doSomething(Gemini.BALL_COLOR_RED)
onBallNumberChanged: console.log("new ball number is", ballNumber) // 10
Component.onCompleted: console.log("default ball number is", ballNumber) // 0
}
}
main.qml中添加了qmlSignal()信号和qmlFunction()函数,信号在QML中发送,函数在C++中调用。
(2)修改Gemini.h
#ifndef GEMINI_H #define GEMINI_H // Gemini.h #include#include class Gemini : public QObject { Q_OBJECT Q_ENUMS(BALL_COLOR) Q_PROPERTY(unsigned int ballNumber READ ballNumber WRITE setBallNumber NOTIFY ballNumberChanged) public: Gemini() : m_ballColor(BALL_COLOR_YELLOW), m_ballNumber(0) { qDebug() << "Gemini::Gemini() called"; } enum BALL_COLOR { BALL_COLOR_YELLOW, BALL_COLOR_RED, BALL_COLOR_BLUE, BALL_COLOR_ALL }; unsigned int ballNumber() const { return m_ballNumber; } void setBallNumber(const unsigned int &ballNumber) { if(ballNumber != m_ballNumber) { m_ballNumber = ballNumber; emit ballNumberChanged(); } } Q_INVOKABLE void stop() { qDebug() << "Gemini::stop() called"; } signals: void begin(); void ballNumberChanged(); public slots: void doSomething(BALL_COLOR ballColor) { qDebug() << "Gemini::doSomething() called with" << ballColor; if(ballColor != m_ballColor) { m_ballColor = ballColor; qDebug() << "ball color changed"; } } void cppSlot(const QString &message) { qDebug() << "Called the C++ slot with message:" << message; // this is a qml signal } private: BALL_COLOR m_ballColor; unsigned int m_ballNumber; }; #endif // GEMINI_H
Gemini类中添加了cppSlot()槽函数,将要在main.cpp中与QML的信号connect。
(3)修改main.cpp
#include#include #include int main(int argc, char *argv[]) { QGuiApplication app(argc, argv); qmlRegisterType ("Union.Lotto.Gemini", 1, 0, "Gemini"); QQmlEngine engine; // set qml context property // Gemini aGemini; // engine.rootContext()->setContextProperty("aGemini", &aGemini); QQmlComponent component(&engine, QUrl(QStringLiteral("qrc:///main.qml"))); QObject *object = component.create(); qDebug() << "width value is" << object->property("width").toInt(); object->setProperty("width", 500); qDebug() << "height value is" << QQmlProperty::read(object, "height").toInt(); QQmlProperty::write(object, "height", 500); QObject *rect = object->findChild ("rect"); if(rect) { rect->setProperty("color", "black"); } QVariant returnedValue; QVariant message = "Hello from C++"; QMetaObject::invokeMethod(object, "qmlFunction", Q_RETURN_ARG(QVariant, returnedValue), Q_ARG(QVariant, message)); qDebug() << "returnedValue is" << returnedValue.toString(); // function from qml Gemini test; QObject::connect(object, SIGNAL(qmlSignal(QString)), &test, SLOT(cppSlot(QString))); return app.exec(); }
在main.cpp中添加了QMeta::invokeMethod()和QObject::connect()来分别访问QML中函数和信号。
7、总结
本文主要介绍了QML与C++混合编程常用的方法与技巧,在使用过程中有几点值得注意:
自定义类一定要派生自QObject类或其子类。
必须使用Q_OBJECT宏。
注册自定义类到Qt元对象系统或设置自定义类对象实例为QML上下文属性是必须的。
两者交互进行数据传递时,要符合QML与C++间数据类型的转换规则。