QML与C++混合编程详解(三)

2015-01-22 21:04:23 · 作者: · 浏览: 18
]) { QGuiApplication app(argc, argv); QQuickView view; Gemini gemini; view.rootContext()->setContextProperty("gemini", &gemini); view.setSource(QUrl(QStringLiteral("qrc:///main.qml"))); view.show(); return app.exec(); }

彻底修改一下main.cpp吧,这里使用了QQuickView,注意头文件的变化,Gemini类先实例化为gemini对象,然后注册为QML上下文属性。

(2)修改main.qml

// main.qml
import QtQuick 2.2
Item {
    width: 360; height: 360
    MouseArea {
        anchors.fill: parent
        onClicked: {
            gemini.begin()
            gemini.stop()
        }
    }
    Connections {
        target: gemini
        onBegin:console.log("aaaa")
    }
}

既然main.cpp修改了那么多东西,main.qml也要做相应的修改,在main.qml中不能使用Gemini类型来实例化了,也不能调用doSomething()槽函数了,因为doSomething()函数中的枚举类型在QML中是访问不到的,正确的用法是通过QML上下文属性“gemini”来访问C++,可以访问信号begin()和成员函数stop(),此时的信号处理器就需要用Connections来处理了,如上面例子中所示。

6C++访问QML

同样,在C++中也可以访问QML中的属性、函数和信号。

在C++中加载QML文件可以用QQmlComponent或QQuickView,然后就可以在C++中访问QML对象了。QQuickView提供了一个显示用户界面的窗口,而QQmlComponent没有。

QQuickView::rootObject()返回了组件实例,是一个有用的函数。前面的例子中已经使用过QQuickView了,下面的例子介绍QQmlComponent的用法。

使用QQmlComponent――

修改main.cpp

// 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"))); component.create(); return app.exec(); }
     
    
   
  

例子中注释的部分是设置QML上下文属性的方法。

C++中访问QML中的属性――

在C++中加载了QML文件并进行组件实例化后,就可以在C++中访问、修改这个实例的属性值了,可以是QML内建属性,也可以是自定义属性。

(1)修改main.qml

// 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"
    Rectangle {
        objectName: "rect"
        anchors.fill: parent
        color: "yellow"
    }
    MouseArea {
        anchors.fill: parent
        onClicked: {
            gemini.begin()
            gemini.stop()
            gemini.ballNumber = 10
        }
    }
    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中添加了一个Rectangle,设置objectName属性值为“rect”,这个值是为了在C++中能够找到这个Rectangle。

(2)修改main.cpp

// 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"); } return app.exec(); }
      
     
    
   
  

首先,使用了QObject::property()/setProperty()来读取、修改width属性值。

接着,使用了QQmlProperty::read()/write()来读取、修改height属性值。

另外,如果某个对象的类型是QQuickItem,例如QQuickView::rootObject()的返回值,这时就可以使用QQuickItem::width/setWidth()来访问、修改width属性值了。

有时候,QML组件是一个复杂的树型结构,包含兄弟组件和孩子组件,我们可以使用QObject::findchild()/findchildren()来查找,如上面例子所示。

C++中访问QML中的函数与信号――

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