在 C++程序中使用 QML技术经验

在 C++程序中使用 QML
QML API 是分为三个主类——QDeclarativeEngine QdeclarativeComponent 与 QDecl arativeContext。QDeclarativeEngine 提供 QML 运行的环境QdeclarativeComponent 封 装了 QML Documents 与 QDeclarativeCohtml


ntext 容许程序导出数据到 QML 组件实例。 QML 还包含了 API 的一个方便 经过 QDeclarativeView 应用程序只须要简单嵌入 QML 组 件到一个新的 QGraphicsView 就能够了。这有许多细节将在下面讨论。QDeclarativeView 主要是用于快速成型的应用程序里。 若是你是从新改进使用 QML 的 Qt 应用程序请参阅 整合 QML 到现有的 Qt UI 代码。 基本用法 每一个应用程序至少需求一个 QDeclarativeEngine。QDeclarativeEngine 容许配置全局设置 应用到全部的 QML 组件实例中 例如 QNetworkAccessManager 是用于网络通讯以及永久 储存的路径。若是应用程序需求在 QML 组件实例间需求不一样的设置只须要多个 QDeclarati veEngine。 使用 QDeclarativeComponent 类载入 QML Documents。每一个 QDeclarativeComponent 实例呈现单一 QML 文档。 QDeclarativeComponent 能够传递一个文档的地址或文档的原始 文本内容。该文档的 URL 能够是本地文件系统的地址或经过 QNetworkAccessManager 支 持的网络地址。 QML 组件实例经过调用 QDeclarativeComponent::create()模式来建立。在这里载入一个 Q ML 文档的示例而且从它这里建立一个对象。 QDeclarativeEngine *engine = new QDeclarativeEngine(parent); QDeclarativeComponent component(engine, QUrl::fromLocalFile(“main.qml”)); QObject *myObject = component.create();
c++


导出数据 QML 组件是以 QDeclarativeContext 实例化的。context 容许应用程序导出数据到该 QML 组件实例中。 单个 QDeclarativeContext 可用于一应用程序的全部实例对象或针对每一个实例 使用 QDeclarativeContext 能够建立更为精确的控制导出数据。若是不传递一个 context 给 QDeclarativeComponent::create()模式那么将使用 QDeclarativeEngine 的 root context。 数据导出经过该 root context 对全部对象实例是有效的。 简单数据 为了导出数据到一个 QML 组件实例应用程序设置 Context 属性而后由 QML 属性绑定 的名称与 JavaScrip 访问。下面的例子显示经过 QGraphicsView 如何导出一个背景颜色到

QML 文件中 //main.cpp #include <QApplication> #include <QDeclarativeView> #include <QDeclarativeContext>

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 显示建立的组件 你就须要使用 Q DeclarativeEngine::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 C ontext 属性改变为红色那么该组件对象实例将自动更新。注意删除任意 QDeclarativeC

ontext 的构造是建立者的事情。当 window 组件实例撤消时再也不须要 windowContext 时w indowContext 必须被消毁。最简单的方法是确保它设置 window 做为 windowContext 的父 级。 QDeclarativeContexts 是树形结构——除了 root context 每一个 QDeclarativeContexts 都有 一个父级。子级 QDeclarativeContexts 有效的继承它们父级的 context 属性。这使应用程序 分隔不一样数据导出到不一样的 QML 对象实例有更多自由性。若是 QDeclarativeContext 设置 一 context 属性一样它父级也被影响新的 context 属性是父级的影子。以下例子中ba ckground 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 NOTIF Y 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 有”run ning”属性这将会是一个很是优秀的 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 要先获取网络数据而后才能够建立对象。在这种状况下 QDecl arativeComponent 将有 Loading status。直到组件调用 QDeclarativeComponent::create() 以前应用程序将一直等待。 下面的例子显示如何从一个网络资源载入 QML 文件。在建立 QDeclarativeComponent 之 后它测试组件是否加载。若是是它链接 QDeclarativeComponent::statusChanged()信 号不然直接调用 continueLoading()。这个测试是必要的甚至 URL 均可以是远程的只 是在这种状况下要防组件是被缓存的。 MyApplication::MyApplication() { // … component = new QDeclarativeComponent(engine, QUrl(“http://www.example.com/mai n.qml”)); if (component->isLoading()) QObject::connect(component, SIGNAL(statusChanged(QDeclarativeComponent::Statu s)), this, SLOT(continueLoading())); else

continueLoading(); }

void MyApplication::continueLoading() { if (component->isError()) { qWarning() << component->errors(); } else { QObject *myObject = component->create(); } }

Qt 资源 QML 的内容可使用 qrcURL 方案从 Qt 资源系统载入。例如 [project/example.qrc] <!DOCTYPE RCC> <RCC version=”1.0″>

<qresource prefix=”/”> <file>main.qml</file> <file>p_w_picpaths/background.png</file> </qresource>

</RCC>

[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: “p_w_picpaths/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 <QtGui/QApplication> #include <QtDeclarative/QDeclarativeView> #include <QtDeclarative/QDeclarativeEngine> #include <QtDeclarative/QDeclarativeComponent> #include <QtDeclarative/QDeclarativeContext> #include <QtDeclarative/QDeclarativeItem> #include <QMetaObject> 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<QDeclarativeItem*>(qmlView.rootObject()); item->setProperty("color", QVariant("blue")); // 查找到咱们须要的节点根均 objectname NeedFindObj 来得到并设置他的文本属性 QDeclarativeItem *item1 = item->findChild<QDeclarativeItem *>("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或者帮助文档到底是不是个人文档里 面没有仍是怎么的缓存

相关文章
相关标签/搜索