×
Namespaces

Variants
Actions

QML与Qt C++ 交互机制探讨与总结

From Nokia Developer Wiki
Jump to: navigation, search
Article Metadata

代码示例
兼容于
平台:
Symbian

文章
cuizhan 在 21 Sep 2011 创建
最后由 hamishwillee 在 13 Jun 2012 编辑

Contents

介绍

QML和 C++对象可以通过,signals,slots和 属性修改进行交互。对于一个C++对象,任何数据都可以通过Qt的 Meta-Object System暴露给QML(何总方法,后面介绍),同时,任何的QML对象数据通过Meta-object system在C++端直接访问。
在实际的项目中很多地方会用到QML与Qt C++交互。在这里总结了若干方法供大家参考,欢迎大家指导和拍砖。

在这里不外乎有三种方法:
1. 把Qt C++中的对象或类型暴露给 QML端,供QML端使用。(官方说法是“嵌入”而非“暴露”,比较文明。- -b)
2. QML中的Signal Handler(相当于Qt C++发送信号给QML端,QML端的Signal Handler进行处理)。
3. 在Qt C++端创建QML对象,既然对象都有了。那你想怎么样它就怎么样它呗。(没用过,看起来也不太实用,不过介绍介绍,有用过的同学留言哈)。

好,我们开始吧~

知识准备

别急,让我们先来看看,一些东西,如果您都知道,可以跳过此节。
QML API有三个主要成员——QDeclarativeEngineQDeclarativeComponentQDeclarativeContext

QDeclarativeEngine提供了QML的运行环境。
QDeclarativeComponent封装了QML Documents
QDeclarativeContext允许程序使用QML组件显示数据。

QML包含一个非常好用的API——QDeclarativeView。通过它,应用程序可以很方便的把QML组件嵌入到QGraphicsView中。QDeclarativeView主要用于在应用程序开发过程中进行快速原型开发。

暴露Qt C++的对象或类型给QML

创建需要暴露给QML的数据类型

#ifndef MYCLASS_H
#define MYCLASS_H
#include <QObject>
#include <QString>
class MyClass : public QObject
{
Q_OBJECT
Q_PROPERTY(QString myString READ myString WRITE setmyString NOTIFY myStringChanged)
public:
explicit MyClass(QObject *parent = 0);
Q_INVOKABLE QString getMyString();
signals:
void myStringChanged();
public slots:
void setmyString(QString aString);
QString myString();
private:
QString m_string;
};
#endif // MYCLASS_H

若你想数据元素中的方法可以被QML直接调用有2种方法:
1. 在函数申明前添加 Q_INVOKABLE 宏。
2. 申明成public slots。

QML可以直接访问改数据元素的属性,该属性由QPROPERTY所申明。
具体实现请参考,示例代码。

暴露已存在的Qt C++对象给QML

//main.cpp
MyClass myObj;
QDeclarativeEngine *engine=viewer.engine();
QDeclarativeContext *context=engine->rootContext();
context->setContextProperty("myObjectExposeByCXProperty", &myObj);

qml中可以直接使用myObjectExposeByCxProperty对象。

//mainpage.qml
...
Button{
...
id:btn1
...
text: qsTr("PROPERTY")
//此处调用myString为MyClass的QPROPERTY的属性不是方法,所以没有括号。
onClicked: label.text=myObjectExposeByCXProperty.myString;
}
...

注册Qt C++类类型给QML

另外一种方式是注册类型

//main.cpp
qmlRegisterType<MyClass>("RegisterMyType", 1, 0, "MyClassType");

QML中这样使用

//mainpage.qml
...
import RegisterMyType 1.0
Button{
id:btn2
...
text: qsTr("INOVKABLE")
//此处调用的时INVOKABLE的方法,不是属性,所以有括号。
onClicked: label.text=myclassExposeByRegType.getMyString();
}
//创建对象,由于QML是解释执行的,所以放后面也没什么关系。
MyClassType
{
id:myclassExposeByRegType
}

步骤:
1. 导入import。
2. 创建对象。
3. id直接使用。

QML中的Signal Handler

还是使用上面的那例子,在qml中点击按钮控件,改变其中对象的字符串,这时候在Qt C++中发送一个signal信号给qml端,qml端接收到使用signal handler响应,改变label2的值。具体代码如下。
qml中修改string的值。

//mainpage.qml
Button{
id:btn3
text: qsTr("emit stringchanged signal")
onClicked: myObjectExposeByCXProperty.myString="xxxxx";
}

Qt C++触发信号

//myclass.cpp
void MyClass::setmyString(QString aString)
{
if(aString==m_string)
{
return;
}
m_string=aString;
emit myStringChanged();
}

连接signal handler响应

//mainpage.qml
Connections
{
target: myObjectExposeByCXProperty
onMyStringChanged:label2.text="Signal handler received"
}

Qt C++中直接调用QML的函数

同样的QML的函数也可以被Qt C++端调用。
所有的QML函数都通过meta-object system暴露Qt C++端,在Qt C++端可以使用QMetaObject::invokeMethod()方法直接调用。下面就是这样的一个例子。

 // MyItem.qml
import QtQuick 1.0
Item {
function myQmlFunction(msg) {
console.log("Got message:", msg)
return "some return value"
}
}
 // main.cpp
QDeclarativeEngine engine;
QDeclarativeComponent component(&engine, "MyItem.qml");
QObject *object = component.create();
QVariant returnedValue;
QVariant msg = "Hello from C++";
QMetaObject::invokeMethod(object, "myQmlFunction",
Q_RETURN_ARG(QVariant, returnedValue),
Q_ARG(QVariant, msg));
qDebug() << "QML function returned:" << returnedValue.toString();
delete object;

注意:QMetaObject::invokeMethod()方法中的参数Q_RETURN_ARG()和Q_ARG()都被定义为QVariant类型,此类型是QML函数的的参数和返回值的通用数据类型。

更多例程可以在SDK的安装目录中:\QtSDK\Examples\4.7\declarative\tutorials\extending 看到。

源码下载

File:QM Call Qt Function.zip

相关链接

Qt Quick (Chinese)

This page was last modified on 13 June 2012, at 13:56.
596 page views in the last 30 days.

Was this page helpful?

Your feedback about this content is important. Let us know what you think.

 

Thank you!

We appreciate your feedback.

×