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

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

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();

导出数据 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>images/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: “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 <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或者帮助文档究竟是不是我的文档里 面没有还是怎么的

时间: 2024-10-14 16:03:46

在 C++程序中使用 QML技术经验的相关文章

常用的项目中使用的技术经验总结(不断补充中)

2018-08-0422:11:19 重要的信息:1.数据库相关: mysql -jdbc连接 驱动名:com.mysql.jdbc.Driver 2.Tomcat相关 : 端口号:默认:8080 :修改后:80823.SSM框架相关常用的注解要使用下面的几个组件,需要在mvc.xml中添加组件扫描的标签,并添加的包的路径添加之后,会在项目启动之后,通过web.xml中的关联配置,将包下有注解的类扫描为bean. @Controller--控制器@Service --服务层 @Autowired

Android技术17:Android应用程序中执行二进制命令

Android系统底层为Liunx内核,内核中有大量的可执行的二进制文件,system/bin目录下面,如下图 我们都知道在Linux命令窗口中可以执行上述命令,但是在Android应用程序中是如何调用该命令呢? 1.获取当前Runtime Runtime.getRuntime(); 2.执行命令 例如执行ps 查看进程信息 Process precess=Runtime.getRuntime().exec("ps"); 3.获取内容 InputStream is=precess.ge

浅谈高大上的微信小程序中渲染html内容—技术分享

大部分Web应用的富文本内容都是以HTML字符串的形式存储的,通过HTML文档去展示HTML内容自然没有问题.但是,在微信小程序(下文简称为「小程序」)中,应当如何渲染这部分内容呢? 解决方案 wxParse 小程序刚上线那会儿,是无法直接渲染HTML内容的,于是就诞生了一个叫做「 wxParse 」的库.它的原理就是把HTML代码解析成树结构的数据,再通过小程序的模板把该数据渲染出来. rich-text 前端精品教程:百度网盘下载 后来,小程序增加了「rich-text」组件用于展示富文本内

资深程序员带你玩转深度学习中的正则化技术(附Python代码)!

目录 1. 什么是正则化? 2. 正则化如何减少过拟合? 3. 深度学习中的各种正则化技术: L2和L1正则化 Dropout 数据增强(Data augmentation) 提前停止(Early stopping) 4. 案例:在MNIST数据集上使用Keras的案例研究 1. 什么是正则化? 在深入该主题之前,先来看看这几幅图: 之前见过这幅图吗?从左到右看,我们的模型从训练集的噪音数据中学习了过多的细节,最终导致模型在未知数据上的性能不好. 换句话说,从左向右,模型的复杂度在增加以至于训练

android菜鸟必看的60个技术经验

最初,android工程师在开发app时,会遇见各种各样的问题,比如数据加载.信息同步等等,其主要原因才开始,会android项目开发(http://www.maiziedu.com/course/android/)不熟悉,还有就是不知道如何处理才妥当,下面小编就整理了网上各位android工程师的一些技术经验分享给大家:  1. 全部Activity可继承自BaseActivity,便于统一风格与处理公共事件,构建对话框统一构建器的建立,万一需要整体变动,一处修改到处有效.  2. 数据库表段

.net中对象序列化技术浅谈

.net中对象序列化技术浅谈 2009-03-11 阅读2756评论2 序列化是将对象状态转换为可保持或传输的格式的过程.与序列化相对的是反序列化,它将流转换为对象.这两个过程结合起来,可以轻松地存储和传输数 据.例如,可以序列化一个对象,然后使用 HTTP 通过 Internet 在客户端和服务器之间传输该对象.反之,反序列化根据流重新构造对象.此外还可以将对象序列化后保存到本地,再次运行的时候可以从本地文件 中“恢复”对象到序列化之前的状态.在.net中有提供了几种序列化的方式:二进制序列化

Java后端程序员1年工作经验总结

java后端1年经验和技术总结(1) 1.引言 毕业已经一年有余,这一年里特别感谢技术管理人员的器重,以及同事的帮忙,学到了不少东西.这一年里走过一些弯路,也碰到一些难题,也受到过做为一名开发却经常为系统维护和发布当救火队员的苦恼.遂决定梳理一下自己所学的东西,为大家分享一下. 经过一年意识到以前也有很多认识误区,比如: 偏爱收集,经常收集各种资料视频塞满一个个硬盘,然后心满意足的看着容量不行动. 不重基础,总觉得很多基础东西不需要再看了,其实不懂的地方很多,计算机程序方面任何一个结果都必有原因

将应用程序中的商业逻辑同对其提供支持的通用服务进行分离(转)

AOP(Aspect-Oriented Programming,面向方面编程),可以说是OOP(Object-Oriented Programing,面向对象编程)的补充和完善.OOP引入封装.继承和多态性等概念来建立一种对象层次结构,用以模拟公共行为的一个集合.当我们需要为分散的对象引入公共行为的时候,OOP则显得无能为力.也就是说,OOP允许你定义从上到下的关系,但并不适合定义从左到右的关系.例如日志功能.日志代码往往水平地散布在所有对象层次中,而与它所散布到的对象的核心功能毫无关系.对于其

程序员接私活经验总结

程序员接私活经验总结 到网上看看,接私活是多么不容易,技术问题本身是个因素,还有很多有技术的人接私活时被骗,或者是合作到最后以失败告终,所以想请有经验的大侠们出来指点一下,接私活是怎么接的?一般流程怎样?要注意什么?签合同的风险?等等问题,希望高手能将宝贵的经验与大家共享阿? ===============================================================================================================