【文件属性】:
文件名称:在C++程序中使用QML
文件大小:64KB
文件格式:DOC
更新时间:2015-01-10 02:12:19
在C++程序中使用QML
在C++程序中使用QML
QML API是分为三个主类——QDeclarativeEngine, QdeclarativeComponent 与 QDeclarativeContext。QDeclarativeEngine 提供QML运行的环境,QdeclarativeComponent 封装了QML Documents 与QDeclarativeContext允许程序导出数据到QML组件实例。
QML还包含了API的一个方便,通过QDeclarativeView 应用程序只需要简单嵌入QML组件到一个新的QGraphicsView就可以了。这有许多细节将在下面讨论。QDeclarativeView 主要是用于快速成型的应用程序里。
如果你是重新改进使用QML的Qt应用程序,请参阅 整合QML到现有的Qt UI代码。
基本用法
每个应用程序至少需求一个QDeclarativeEngine。QDeclarativeEngine允许配置全局设置应用到所有的QML组件实例中,例如QNetworkAccessManager是用于网络通信以及永久储存的路径。如果应用程序需求在QML组件实例间需求不同的设置只需要多个QDeclarativeEngine。
使用QDeclarativeComponent类载入QML Documents。每个QDeclarativeComponent实例呈现单一QML文档。QDeclarativeComponent可以传递一个文档的地址或文档的原始文本内容。该文档的URL可以是本地文件系统的地址或通过QNetworkAccessManager支持的网络地址。
QML组件实例通过调用QDeclarativeComponent::create()模式来创建。在这里载入一个QML文档的示例并且从它这里创建一个对象。
QDeclarativeEngine *engine = new QDeclarativeEngine(parent);
QDeclarativeComponent component(engine, QUrl::fromLocalFile(“main.qml”));
QObject *myObject = component.create();
导出数据
QML组件是以QDeclarativeContext实例化的。context允许应用程序导出数据到该QML组件实例中。单个QDeclarativeContext 可用于一应用程序的所有实例对象或针对每个实例使用QDeclarativeContext 可以创建更为精确的控制导出数据。如果不传递一个context给QDeclarativeComponent::create()模式;那么将使用QDeclarativeEngine的root context。数据导出通过该root context对所有对象实例是有效的。
简单数据
为了导出数据到一个QML组件实例,应用程序设置Context属性;然后由QML属性绑定的名称与JavaScrip访问。下面的例子显示通过QGraphicsView如何导出一个背景颜色到QML文件中:
//main.cpp
#include
#include
#include
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QDeclarativeView view;
QDeclarativeContext *context = view.rootContext();
context->setContextProperty(“backgroundColor”,
QColor(Qt::yellow));
view.setSource(QUrl::fromLocalFile(“main.qml”));
view.show();
return app.exec();
}
//main.qml
import Qt 4.7
Rectangle {
width: 300
height: 300
color: backgroundColor
Text {
anchors.centerIn: parent
text: “Hello Yellow World!”
}
}
或者,如果你需要main.cpp不需要在QDeclarativeView显示创建的组件,你就需要使用QDeclarativeEngine::rootContext()替代创建QDeclarativeContext实例。
QDeclarativeEngine engine;
QDeclarativeContext *windowContext = new QDeclarativeContext(engine.rootContext());
windowContext->setContextProperty(“backgroundColor”, QColor(Qt::yellow));
QDeclarativeComponent component(&engine, “main.qml”);
QObject *window = component.create(windowContext);
Context属性的操作像QML绑定的标准属性那样——在这个例子中的backgroundColor Context属性改变为红色;那么该组件对象实例将自动更新。注意:删除任意QDeclarativeContext的构造是创建者的事情。当window组件实例撤消时不再需要windowContext时,windowContext必须被消毁。最简单的方法是确保它设置window作为windowContext的父级。
QDeclarativeContexts 是树形结构——除了root context每个QDeclarativeContexts都有一个父级。子级QDeclarativeContexts有效的继承它们父级的context属性。这使应用程序分隔不同数据导出到不同的QML对象实例有更多*性。如果QDeclarativeContext设置一context属性,同样它父级也被影响,新的context属性是父级的影子。如下例子中,background context属性是Context 1,也是root context里background context属性的影子。
结构化数据
context属性同样可用于输出结构化与写数据到QML对象。除了QVariant支持所有已经存在的类型外,QObject 派生类型可以分配给context属性。 QObject context属性允许数据结构化输出并允许QML来设置值。
下例创建CustomPalette对象并设置它作为palette context属性。
class CustomPalette : public QObject
{
Q_OBJECT
Q_PROPERTY(QColor background READ background WRITE setBackground NOTIFY backgroundChanged)
Q_PROPERTY(QColor text READ text WRITE setText NOTIFY textChanged)
public:
CustomPalette() : m_background(Qt::white), m_text(Qt::black) {}
QColor background() const { return m_background; }
void setBackground(const QColor &c) {
if (c != m_background) {
m_background = c;
emit backgroundChanged();
}
}
QColor text() const { return m_text; }
void setText(const QColor &c) {
if (c != m_text) {
m_text = c;
emit textChanged();
}
}
signals:
void textChanged();
void backgroundChanged();
private:
QColor m_background;
QColor m_text;
};
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QDeclarativeView view;
view.rootContext()->setContextProperty(“palette”, new CustomPalette);
view.setSource(QUrl::fromLocalFile(“main.qml”));
view.show();
return app.exec();
}
QML引用palette对象以及它的属性,为了设置背景与文本的颜色,这里是当单击窗口时,面板的文本颜色将改变成蓝色。
import Qt 4.7
Rectangle {
width: 240
height: 320
color: palette.background
Text {
anchors.centerIn: parent
color: palette.text
text: “Click me to change color!”
}
MouseArea {
anchors.fill: parent
onClicked: {
palette.text = “blue”;
}
}
}
可以检测一个C++属性值——这种情况下的CustomPalette的文本属性改变,该属性必须有相应的NOTIFY信息。NOTIFY信号是属性值改变时将指定一个信号发射。
实现者应该注意的是,只有值改变时才发射信号,以防止发生死循环。访问一个绑定的属性,没有NOTIFY信号的话,将导致QML在运行时发出警告信息。
动态结构化数据
如果应用程序对结构化过于动态编译QObject类型;那么对动态结构化数据可在运行时使用QDeclarativePropertyMap 类构造。
从QML调用 C++
通过public slots输出模式或Q_INVOKABLE标记模式使它可以调用QObject派生出的类型。
C++模式同样可以有参数并且可以返回值。QML支持如下类型:
•bool
•unsigned int, int
•float, double, qreal
•QString
•QUrl
•QColor
•QDate,QTime,QDateTime
•QPoint,QPointF
•QSize,QSizeF
•QRect,QRectF
•QVariant
下面例子演示了,当MouseArea单击时控制“Stopwatch”对象的开关。
//main.cpp
class Stopwatch : public QObject
{
Q_OBJECT
public:
Stopwatch();
Q_INVOKABLE bool isRunning() const;
public slots:
void start();
void stop();
private:
bool m_running;
};
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QDeclarativeView view;
view.rootContext()->setContextProperty(“stopwatch”,
new Stopwatch);
view.setSource(QUrl::fromLocalFile(“main.qml”));
view.show();
return app.exec();
}
//main.qml
import Qt 4.7
Rectangle {
width: 300
height: 300
MouseArea {
anchors.fill: parent
onClicked: {
if (stopwatch.isRunning())
stopwatch.stop()
else
stopwatch.start();
}
}
}
值得注意的是,在这个特殊的例子里有更好的方法来达到同样的效果,在main.qml有”running”属性,这将会是一个非常优秀的QML代码:
// main.qml
import Qt 4.7
Rectangle {
MouseArea {
anchors.fill: parent
onClicked: stopwatch.running = !stopwatch.running
}
}
当然,它同样可以调用 functions declared in QML from C++。
网络组件
如果URL传递给QDeclarativeComponent是一网络资源或者QML文档引用一网络资源,QDeclarativeComponent要先获取网络数据;然后才可以创建对象。在这种情况下QDeclarativeComponent将有Loading status。直到组件调用QDeclarativeComponent::create()之前,应用程序将一直等待。
下面的例子显示如何从一个网络资源载入QML文件。在创建QDeclarativeComponent之后,它测试组件是否加载。如果是,它连接QDeclarativeComponent::statusChanged()信号,否则直接调用continueLoading()。这个测试是必要的,甚至URL都可以是远程的,只是在这种情况下要防组件是被缓存的。
MyApplication::MyApplication()
{
// …
component = new QDeclarativeComponent(engine, QUrl(“http://www.example.com/main.qml”));
if (component->isLoading())
QObject::connect(component, SIGNAL(statusChanged(QDeclarativeComponent::Status)),
this, SLOT(continueLoading()));
else
continueLoading();
}
void MyApplication::continueLoading()
{
if (component->isError()) {
qWarning() << component->errors();
} else {
QObject *myObject = component->create();
}
}
Qt资源
QML的内容可以使用qrc:URL方案从Qt 资源系统载入。例如:
[project/example.qrc]
main.qml
images/background.png
[project/project.pro]
QT += declarative
SOURCES += main.cpp
RESOURCES += example.qrc
[project/main.cpp]
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QDeclarativeView view;
view.setSource(QUrl(“qrc:/main.qml”));
view.show();
return app.exec();
}
[project/main.qml]
import Qt 4.7
Image {
source: “images/background.png”
}
请注意,资源系统是不能从QML直接访问的。如果主QML文件被加载作为资源,所有的文件指定在QML中做为相对路径从资源系统载入。在QML层使用资源系统是完全透明的。这也意味着,如果主QML文件没有被加载作为资源,那么从QML不能访问资源系统。
1.这里主要是介绍,如何在c++中调用QML中的函数和设置QML中的属性的问题
2.具体代码
// UICtest.qml
import Qt 4.7
Rectangle {
id: mainWidget;
width: 640
height: 480
function callbyc(v)
{
mainWidget.color = v;
return "finish";
}
Rectangle{
id: secondRect;
x: 100;
y: 20;
width: 400;
height: 300;
Rectangle{
x: 10;
y: 20;
width: 30;
height: 40;
color: "#FF035721"
Text {
objectName: "NeedFindObj";
anchors.fill: parent;
text: "";
}
}
}
}
// main.cpp
#include
#include
#include
#include
#include
#include
#include
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QDeclarativeView qmlView;
qmlView.setSource(QUrl::fromLocalFile("../UICtest/UICtest.qml"));
qmlView.show();
// 获取根节点,就是 QML中 id是mainWidget的节点
QDeclarativeItem *item = qobject_cast(qmlView.rootObject());
item->setProperty("color", QVariant("blue"));
// 查找到我们需要的节点根均objectname NeedFindObj 来获得,并设置他的文本属性
QDeclarativeItem *item1 = item->findChild("NeedFindObj");
if (item1)
{
item1->setProperty("text", QVariant("OK"));
}
// 调用QML中的函数, 分别是 函数所在的对象, 函数名,返回值, 参数
QVariant returnVar;
QVariant arg1 = "blue";
QMetaObject::invokeMethod(item, "callbyc",
Q_RETURN_ARG(QVariant, returnVar),Q_ARG(QVariant, arg1));
qDebug(" %s",returnVar.toString().toLocal8Bit().data());
return a.exec();
}
说明:
这里的根节点是id为mainWidget的矩形元素,那么在C++中获取根节点后就可以,直接的设置他的属性了。其他属性也可以同样,调用指定节点内的函数是通过QMetaObject中的invokeMethod 来进行调用的。
最后所有关于QML和c++交互部分就基本写完,如果想要更多的东西,或者一些其他方法,强烈看看
http://doc.qt.nokia.com/4.7-snapshot/qtbinding.html,或者帮助文档,(究竟是不是我的文档里面没有还是怎么的)