QML和C++混合编程--在C++应用程序中使用QML
来源:互联网 发布:解不定积分软件 编辑:程序博客网 时间:2024/05/22 12:06
QML很容易从C++进行扩展,在Qt Declarative模块的类允许从C++加载和操纵QML组件,而且通过Qt的元素对象系统,QML和C++对象是可以容易通过Qt信号和槽进行通信的。
QML和C++混合编程原因:
a. 使用定义在C++源中的功能(例如,当使用一个C++基于Qt的数据模型,或者调用第三方C++库中的函数)
b. 访问Qt Declarative模块中的功能(例如,使用QDeclarativeImageProvider来动态创建图像)
c. 编写自己的QML元素
要使用Qt Declarative模块,必须先包含和连接合适的模块。Using QML in C++ Application。
1. 核心模块类
Qt Declarative模块提供了一组C++接口来实现从C++扩展QML应用程序,将QML嵌入到C++应用程序中。Qt Declarative模块中有几个核心类提供了完成该任务的基本功能。
a. QDeclarativeEngine: 一个QML引擎提供了执行QML代码的环境,每个应用程序至少需要一个引擎实例。
b. QDeclarativeComponent: 一个组件封装了一个QML文件
c. QDeclarativeContext: 上下文运行应用程序将数据暴露给引擎创建的QML组件
QDeclarativeEngine允许将全局设置应用到它的所有QML组件实例上,例如,QNetworkAccessManager用于网络通信,一个文件路径用作永久性存储等。而QDeclarativeComponent用来加载QML文件,每一个QDeclarativeComponent实例表示一个独立的文件。一个QDeclarativeComponent可以从一个URL、一个QML文件的路径或者原始的QML代码创建,可以通过QDeclarativeComponent::create()函数进行实例化:
QDeclarativeEngine engine;QDeclarativeComponent component(&engine, QUrl::fromLoacalFile("MyRectangle.qml"));QObject * ractangleInstance = component.create();//...delete rectangleInstance;QML 文件也可以使用QDeclarativeView加载,这个类提供了一个方便的基于QWidget的视图,它将QML组件嵌入到一个基于QGraphicsView的应用程序。
2. 混合使用QML和C++的方法
这里提供了几种方法来通过C++扩展QML应用程序,
a. 加载一个QML组件,然后通过C++对其进行操作
b. 直接将一个C++对象及其属性嵌入到QML组件;
c. 定义一个新的QML元素(通过基于QObject的C++类)并在QML代码中创建它们
这些方法不具有排他性,可以在应用程序中同时使用多种方法。
3. 从C++中加载一个QML组件
一个QML文件可以使用QDeclarativeComponent或者QDeclarativeView加载。QDeclarativeComponent将一个QML组件加载为一个C++对象;QDeclarativeView直接将QML组件加载到一个QGraphicsView中。
如果使用QDeclarativeComponent,需要调用QDeclarativeComponent::create()来创建该组件的一个新的实例:
QDeclarativeEngine engine;QDeclarativeComponent component(&engine, QUrl::fromLocalFile("MyIem.qml"));QObject * object = component.create(); ...delete object;如果使用QDeclarativeView,那么它会自动创建该组件的实例,后面可以通过函数QDeclarativeView::rootObject()来获取实例:
QDeclarativeView view;view.setSource(QUrl::formLoacalFile("MyItem.qml"));view.show();QObject * object = view.rootObject这里的object是新创建的MyItem.qml组件的实例,可以使用QObject::setProperty()或者QDeclarativeProperty来修改该项目的属性:
objec->setProperty("width", 200);QDeclarativeProperty(object, "width").write(500);另外,也可以先将对象转换为真实的类型,然后电泳编译时安全的函数。在这里MyItem.qml的基对象是一个Item,它由QDeclarativeItem类进行定义
QDeclarativeItem * item = qobject_cast<QDeclarativeItem * >(object);item->setWidth(500);QML组件本质上是一个包含孩子的对象树,而孩子对象可以拥有兄弟和它自己的孩子。可以使用QObject::objectNam属性和QObject::findChild()函数来定位QML组件的子对象。MyItem.qml中项目有一个Rectangle子项目:
import QtQuick 1.0Item { width: 100; height: 100 Rectangle { anchors.fill: parent objectName: "rect" }}定位孩子:
QObject * rect = object->findChild<QObject *>("rect");if(rect) rect->setProperty("color", "red")如果objectName用在一个ListView或者Repeater的委托中或者其他一些使用 委托创建多个实例的元素中,那么会有多个孩子使用个相同的objectName。这种情况下使用QObject::findChildren()来查找所有匹配objectName的孩子。
4. 在QML组件中嵌入C++对象
在加载一个QML场景到C++应用程序中时,直接嵌入C++数据到QML对象是很有用的。这个可以通过QDeclarativeContext来实现,它可以将数据暴露给QML组件的上下文,允许将数据从C++注入到QML中。例如,这里有一个QML项目引用了一个currentDateTime值,而该值并没有在当前的作用域:
//MyItem.qmlimport QtQuick 1.0Text { text: currentDateTime}这里的currentDateTime值可以直接在加载了该QML组件的C++应用程序中设置,这里需要使用QDeclarativeContext::setContextProperty():
QDeclarativeView view;view.rootContext()-> setContextProperty("currentDateTime", QDateTime::currentDateTime());view.setSource(QUrl::fromLoacalFile("MyItem.qml"));view.show();上下文属性可以使用QVariant或者QObject * 值,这也就意味着自定义的C++对象也可以使用这种方式进行注入,而且这些对象可以直接在QML中进行读取和修改。
如果在QML中调用一个C++函数,那么这个函数必须是一个Qt槽,或者该函数使用Q_INVOKEABLE宏进行标记,这里就是使用了该宏对函数进行了标记。
applicationdata.h文件:
#include <QObject>#include <QDateTime>class ApplicationData : public QObject{ Q_OBJECT public: Q_INVOKABLE QDateTime getCurrentData\eTime() const { return QDateTime::currentDateTime(); }}qml加载
QDeclarativeView view;Application data;view.rootContext()->setContextProperty("applicationData", &data);view.setSource(QUrl::fromLocalFile("../myDeclarativeContext/MyItem.qml"));view.show();
使用了QDeclarativeContext::setContextProperty()设置了applicationData对象,可以在QML文件中直接访问它。最后向项目添加新的MyItem.qml文件。
import QtQuick 1.0Text{text:applicationData.getCurrentDateTime()}C++代码中调用QML组件中的函数,使用QMetaObject::invokeMethod()函数来实现。如MyItem.qml中有一个函数:
import QtQuick 1.0Item { function myQmlFunction(msg) { console.log("Got message: ", msg); return "some return value" }}C++应用程序使用该QML函数:
QDeclarativeEngine engine;QDeclarativeComponent component(&engine, "MyItem.qml");QObject * object = component.crate();QVariant msg = "Hello from C++";QMetaObject::invokeMethod(object, "myQmlFunction", Q_RETURN_ARG(QVarient, returnedVealue), Q_ARG(QVariant, msg));qDebug<<"QML function returned:" << returnedValue.toString();delete object;
在QMetaObject::invokeMethod()函数的Q_RETURN_ARG()和Q_ARG()参数必须指定为QVariant类型,分别用于接收返回值和传递函数参数。
如果QML需要从上下文属性中接收一个信号,可以使用Connection元素进行关联。如果ApplicationData拥有一个叫dataChanged()的信号,那么可以在Connection对象中使用一个onDataChanged处理器来关联该信号:
Text { text:applicationData.getCurrentDateTime() Connections { target: applicationData onDataChanged: console.log("The application data changed!") }}而对于QML中的信号在C++中是自动可用的,可以像关联普通的Qt C++信号一样来对其进行关联。
import QtQuick 1.0Item{ id: item width:100; heigth:100 signal qmlSignal(string msg) Mouse { anchors.fill:parent onClicked: item.qmlSingal("Hello from QML") }}假如在C++代码中有一个MyClass类,它有一个cppSlot()槽,那么可以这样进行关联:
QDeclarativeView view(QUrl::fromLocalFile("MyItem.qml"));QObject * item = view.rootObject();MyClass myClass;QObject::connect(item, SIGNAL(qmlSignal(QString)),&myClass, SLOT(cppSlot(QString)));
5. 定义一个新的QML元素
新的QML元素可以在QML元素中进行定义,它们也可以使用C++类来定义。事实上,很多核心QML元素都是通过C++类实现的。当使用这些元素中的一个来创建一个QML对象时,也就是创建了一个基于QObject的C++类的实例并且设置了属性。例如,下面的ImageViewer类有一个image路径属性:
#include <QtCore>#include <QtDeclarative>class ImageViewer: public QdeclarativeItem//继承自QDeclarativeItem{ Q_OBJECT Q_PROPERTY(QUrl Imge READ Imge WRITE setImge NOTIFY ImgeChanged)public: void setImage(const QUrl &url); QUrl image() const;signals: void imageChanged();}使用qmlRegisterType()使用在QML引擎进行注册:
qmlRegisterType<ImageViewer>("MyLibrary", 1, 0, "ImageViewer");
这时,任何在C++应用程序或者插件中加载的QML代码都可以创建一个ImageViewer对象:
import MyLibrary 1.0
ImageViewer{image: "simle.png"}
自定义的C++类型不一定非要继承自QDeclarativeItem,只有在其是一个可显示的项目时才是必须的。如果该项目时不可以显示的,那么它可以继承自QObject。
新的QML元素的内容:Qt 帮助--Writing QML extensions with C++关键字。
- QML和C++混合编程--在C++应用程序中使用QML
- C++和QML混合编程
- qml和widget混合编程
- Qt中关于JavaScript/QML和C++混合编程
- QML和C++混合编程--QML中的全局对象
- 详解QML与C++混合编程使用
- QML与C++混合编程使用
- QML与C++混合编程使用
- QML与C++混合编程使用
- QAbstractListModel:Qml 使用C++model
- ObjectModel:Qml 使用C++model
- 在QML中使用定时器
- 在QML中使用alarm
- qml中注册和使用C++对象,以及在qml中实现窗体最大最小化
- QML与C++混合编程
- QML与c++混合编程
- QML, Qt C++混合编程
- QML与C++混合编程
- iOS的hook方案: Method Swizzling
- VMWare下虚拟机ubuntu与宿主机windows文件共享
- 《互联网+她时代:女性创业者报告》
- iOS解析--自动无限循环UIScrollView原理
- dubbo
- QML和C++混合编程--在C++应用程序中使用QML
- CCdirector的几个主要功能
- RMI、Hessian、Burlap、Httpinvoker、WebService的比较
- jdk安装都通过了,eclispe却打不开
- iOS应用架构谈 网络层设计方案
- 如何查看eclipse的版本
- KVM安装排错
- java-String中的 intern()
- 解决Webstorm通过Chrome无法调用JB插件调试的问题