C++与QML的集成
来源:互联网 发布:金川集团网络学校 编辑:程序博客网 时间:2024/05/20 22:29
而在混合使用时,遇到的几个问题无非就是:
怎样把QML文件加载到C++中,把它的内容显示出来。
C++和QML之间值的传递是怎样实现的。
针对这两点,同时加上对官网给出的教程,我也和大家分享一下我的理解。
在C++中加载QML
我们先新建一个名为test的标准空白项目(默认的功能是在屏幕上显示”helloworld”):
File->New->Blackberry Project->Cascades->Next->Standard empty project(空白项目)->输入项目名称test->Finish。
项目建立后,我们查看Tset.cpp(在最新的NDK会变成applicationui.cpp)
QmlDocument *qml = QmlDocument::create("asset:///main.qml").parent(this); // create root object for the UI AbstractPane *root = qml->createRootObject<AbstractPane>(); // set created root object as a scene app->setScene(root);
从这里可以看出,加载QML文件有三个步骤
1、创建一个QmlDocument对象,指定你的QML文件路径(注意路径格式)。
2、使用对象的createRootObject()方法创建QML文件内容的根节点。
3、通过setScene()方法把该根节点显示出来。
通过这三个步骤,就能把QML的内容完全显示到屏幕上了。
修改QML的属性
通过setProperty()方法能够在C++中修改QML的一些属性,但是有三个前提:
1、使用这个方法的对象必须属于QObject类
2、QML中组件必须有一个id名
3、在QML中为属性设置一个别名
下面这个例子,通过setProperty()把id为label的Label组件的text属性改为”new text”
Page {
//为id为label的组件的ltext属性设置一个别名labelText
property alias labelText: label.text
Container { Label { id: label text: "Label" } }}
//在C++中使用setProperty()方法 //把id为label的组件的text改为”New text” root->setProperty("labelText", "New text");
访问子对象
QML 文件是树形结构的,所以我们可以利用QObject::findChild()来寻找它的子对象。前提是QML组件有一个objectName。
下面这个例子,通过findChild()找到objectName为”button”的按钮,并用setProperty()来改变按钮的文字。
QObject *newButton = root->findChild<QObject*>("button");newButton->setProperty("text", "New button text");
暴露C++的值给QML
使用QDeclarativePropertyMap这个类能够很方便地将对象的值传递到QML当中。
下面这个例子说明了怎样把C++中的名字和号码传递到QML当中:
QmlDocument *qml = QmlDocument::create("asset:///main.qml"); QDeclarativePropertyMap* propertyMap = new QDeclarativePropertyMap;propertyMap->insert("name", QVariant(QString("Wes Barichak")));propertyMap->insert("phone", QVariant(QString("519-555-0199"))); qml->setContextProperty("propertyMap", propertyMap);
定义好后,我们就可以直接使用了。
Label { text: "User name: " + propertyMap.name}Label { text: "Phone number: " + propertyMap.phone}
暴露C++的对象给QML
为了能够把C++的对象传递给QML,我们需要先在头文件中调用Qt的几个重要的宏。
Q_OBJECT 使用信号槽机制所必须的宏。
Q_PROPERTY 暴露类属性给QML,它可以定义从属性中读取的和写进属性中的值, 同时还可以定义当属性值改变是所触发的信号。
Q_INVOKABLE 暴露成员方法,这样能在QML中调用它们。
下面是一个头文件,这个类有一个属性value,它有三个方法,分别为:value(),setValue()和reset(),通过在reset()方法前加上Q_INVOKABLE,使它能在QML中调用。同时,头文件也定义了当值改变时所触发的信号valueChanged。
#ifndef MYCPPCLASS_H_ #define MYCPPCLASS_H_ #include <QObject> #include <QMetaType> class MyCppClass : public QObject { Q_OBJECT Q_PROPERTY(int value READ value WRITE setValue NOTIFY valueChanged) public: MyCppClass(); virtual ~MyCppClass(); Q_INVOKABLE void reset(); int value(); void setValue(int i); signals: void valueChanged(int); private: int m_iValue; }; #endif
接着,在源文件中实现头文件中的定义
#include "MyCppClass.h" MyCppClass::MyCppClass() { m_iValue = 0; } MyCppClass::~MyCppClass() { } int MyCppClass::value() { return m_iValue; } void MyCppClass::setValue(int i) { m_iValue = i; emit valueChanged(m_iValue); } void MyCppClass::reset() { m_iValue = 0; emit valueChanged(m_iValue); }
为了把MyCppClass暴露给QML,我们先创建一个实例,再用setContextProperty()暴露出来。
MyCppClass *cppObject = new MyCppClass(); qml->setContextProperty("cppObject", cppObject);
这时候,已经能在QML使用对象cppObject了。由于我们在头文件里使用了那3个宏,所以现在我们能够使用cppObject的属性value和方法reset()。
Label { text: "Value of cppObject: " + cppObject.value }
在Q_PROPERTY中,我们还定义了一个信号valueChanged,所以我们可以在QML中写一个槽,连接到这个信号,通过这个办法来改变value的值。
下面这个例子,按钮每按一次,value的值加1。这个按钮自定义了一个槽来连接valueChanged()这个信号,当槽被调用时,改变按钮上的文字。而reset按钮这调用方法reset()来重置value的值。
Button { id: increaseButton text: "Increase the value" onClicked: { cppObject.valueChanged.connect (increaseButton.onCppValueChanged); cppObject.value = cppObject.value + 1; } function onCppValueChanged (val) { increaseButton.text = "Set value to " + (val + 1); } } Button { id: resetButton text: "Reset the value" onClicked: { cppObject.reset () } } Label { id: valueLabel text: "The value is " + cppObject.value }
在QML中使用C++的类
我们也可以直接在QML中使用C++中已经存在的类。实现的方法有两个:
1、使用UIObject::attachedObjects把类(必须继承自QObject)附加到已经存在的QML组件当中。
例如,在QML中使用QTimer:
首先,我们要在C++中对这个类进行注册:
qmlRegisterType<QTimer>("my.library", 1, 0, "QTimer");
需要注意的是这个语句必须在加载QML文件的语句之前,也就是说你必须先注册,再加载。如下:
qmlRegisterType<QTimer>("my.library", 1, 0, "QTimer");QmlDocument *qml = QmlDocument::create("asset:///main.qml").parent(&app);
注册后,我们就能在QML中创建QTimer对象。下面这个例子中,我们把QTimer对象附加到一个Label上。当页面被创建时,计时器就会被触发。计时完成后,Label的文字便会被替换。
import bb.cascades 1.0 import my.library 1.0 Page { Label { id: timerTestLabel text: "Hello world" attachedObjects: [ QTimer { id: timer interval: 1000 onTimeout :{ timerTestLabel.text = "Timer triggered" } } ] } onCreationCompleted: { timer.start(); } }
2、使用CustomControl来拓展类,然后在QML中直接使用。
使用CustomControl,我们能够直接在QML中使用C++的类,不必把它附加到任何QML的组件当中。例子如下:我们新建一个继承CustomControl的类,叫作TextControl,它有text属性,setText()方法,还有一个当文字改变时被触发的信号。
#include <QObject> #include <QString> #include <bb/cascades/CustomControl> class TextControl : public bb::cascades::CustomControl { Q_OBJECT Q_PROPERTY(QString text READ text WRITE setText NOTIFY textChanged) public: QString text(); void setText(QString text); signals: void textChanged(); };
然后,我们在C++中注册,这样才能在QML中使用。
qmlRegisterType<TextControl>("my.library", 1, 0, "TextControl");
此语句同样要放在加载QML文件的语句之前。
注册后,我们同样需要在QML中引入,接着就像其它组件一样使用了。
import bb.cascades 1.0 import my.library 1.0 Page { TextControl { text: "Custom text control" } }
在QML中注入C++对象
我们可以在C++中创建对象然后把它动态地注入到QML当中。
首先我们为QML的容器定义一个objectName,例如:
Page { Container { objectName: "rootContainer" } }
接着,我们把QML文件加载到C++中,并使用QML文件中的根创建了一个Page对象。再用findChild()来寻找对objectName为”rootContainer”的Container。
QmlDocument *qml = QmlDocument::create("main.qml"); // Sets the context property that we want to use from within QML. // Functions exposed via Q_INVOKABLE will be found with this // property name and the name of the function. qml->setContextProperty("injection", this); // Creates the root using the page node Page *appPage = qml->createRootNode<Page>(); // Retrieves the root container from the page Container *container = appPage->findChild<Container*>("rootContainer");
现在,我们就能够在rootContainer中加入我们需要动态增加的内容了。
container->add(Container::create() .background(image) .preferredSize(200,200));
通过这个方法,我们也能够在C++中利用objectName标签来动态地删除、替换、或者插入QML组件。
好了,关于C++与QML的对象和值的传递我暂时也只了解这么多,欢迎大家一起讨论。
文章参考地址:黑莓官网教程
- C++与QML的集成
- QML与C++的集成
- python与c的集成
- python与c的集成
- QML与C++的交互
- qml与C++的交互
- QML的Window与ApplicationWindow
- TCL/TK 与 C 程序的集成
- TCL/TK 与 C 程序的集成
- TCL/TK 与 C 程序的集成
- TCL/TK 与 C 程序的集成
- Python与C集成
- QML多页面的创建与返回
- qml与c++之间的交互
- QML与c++交互的一些坑
- QtQuick 中的 qml 与 Qt 的 C++
- QtQuick 中的 qml 与 Qt 的 C++
- QtQuick 中的 qml 与 Qt 的 C++
- .net MVC3起步
- windbg命令分类与概述
- 修改PHP的默认时区
- 中国天气网API
- 经典字典树模板
- C++与QML的集成
- JAVA 正则表达式 (超详细)
- const int *p,int *const p区别
- SGU 154. Factorial
- SGU 102(欧拉函数)
- android 2.3.7 miui rom的修改
- 2013编程之美 初赛 传话游戏
- 第七届北京交通大学ACM程序设计竞赛网络预赛二
- 大数相加