`
ydbc
  • 浏览: 720541 次
  • 性别: Icon_minigender_1
  • 来自: 大连
文章分类
社区版块
存档分类
最新评论

在C++程序中使用QML

 
阅读更多


本文翻译自Using QML in C++ Applications。欢迎大家编辑、修改此文章。

QML API有三个主要成员——QDeclarativeEngineQDeclarativeComponentQDeclarativeContext

QDeclarativeEngine提供了QML的运行环境。QDeclarativeComponent封装了QML DocumentsQDeclarativeContext允许程序使用QML组件显示数据。

QML包含一个非常好用的API——QDeclarativeView。通过它,应用程序可以很方便的把QML组件嵌入到QGraphicsView中。QDeclarativeView主要用于在应用程序开发过程中进行快速原型开发,它的主要特性将在下面讨论。

如果你正打算用QML改造现有的Qt应用程序,请参考QML与Qt UI代码整合

基本用法

若想将QML与C++程序结合,程序中至少需要一个QDeclarativeEngine。只有程序中需要使用多个不同的QML组件实例时,才需要多个QDeclarativeEngine。为了使所有QML组件实例可以工作,QDeclarativeEngine为他们提供全局配置,QDeclarativeEngine对于C++中使用QML的作用如同QNetworkAccessManager对于网络通信、路径对于持久化存储的作用。

可以使用QDeclarativeComponent加载QML Documents。每一个QDeclarativeComponent实例对应一个QML document。

可以传递一个Document URL或者表示Document内容的原始文本给QDeclarativeComponent。Document URL可以是本地文件系统URL,或者任何QNetworkAccessManager支持的网络URL。

可以通过QDeclarativeComponent::create()方法创建QML组件实例。下面的代码演示了如何加载一个QML Document并创建一个实例:

QDeclarativeEngine *engine = new QDeclarativeEngine(parent);
QDeclarativeComponent component(engine, QUrl::fromLocalFile("main.qml"));
QObject *myObject = component.create();

暴露数据(Exposing Data)

QML组件在QDeclarativeContext中实例化。一个上下文(context)允许程序暴露数据给QML组件实例。一个QDeclarativeContext可用于创建应用程序中用到的所有对象实例,如果需要精确控制为每个实例暴露的数据,可以创建多个QDeclarativeContex。如果上下文(context)没有传递给QDeclarativeComponent::create()方法,将默认使用QDeclarativeEngine的根上下文(root context),这时数据通过跟上下文(root context)暴露给所有对象实例。

简单数据(Simple Data)

向QML组件实例暴露数据,通过QML属性绑定(Property Bindings)和JavaScript对象访问应用程序设置上下文属性(context properties)。下面的例子展示了如何通过QDeclarativeView暴露背景颜色给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 QtQuick 1.0

 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 Properties)的工作方式同QML绑定(QML bindings)中的普通属性(normal properties)一样,在上面的例子中,当上下文属性(context poperty)backgroundColor变为红色时,组件对象实例都会自动更新。请注意创建者有责任删除它创建的QDeclarativeContext。当销毁Window组件时,windowContext必须被显式的销毁(手动delete),或者用一种更简单的方法——设置windowContext的父类为window(父对象释放时,会自动释放所有子对象)。

QDeclarativeContexts以树状结构组织,除了根上下文(root context)外,每个QDeclarativeContext都有一个父对象。QDeclarativeContexts子对象有效的继承父对象的上下文属性(context properties),这使得应用程序更加灵活的在不同的QML对象实例间暴露(exposed)数据。如果QDeclarativeContext设置了一个与父对象相同的上下文属性(context property),父对象的这个属性将被“隐藏”。如下面的例子所示,Context1中的上下文属性(context property)background“隐藏”了根上下文(root context)中的background属性。



结构化数据(Structed Data)

上下文属性(context property)还可用于向QML对象暴露结构化可写数据。除了QVariant已经支持的所有类型外,派生自QObject的类型也可分配给上下文属性(context property)。QObject上下文属性(context property)允许暴露结构化的数据,并允许QML对这些数据设值。 下面的例子创建了一个CustomPalette对象,并将它设为名为palette的上下文属性(context property):

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对象及它的属性来设置背景和文字颜色。当窗口被点击时,palette的颜色将被改变,窗口文本也会被相应的更新:

import QtQuick 1.0

 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产生一个运行时的警告。

动态结构数据(Dynamic Structured Data)

如果一个应用程序在编译期具有很多QObject类型的动态结构化数据,可以使用QDeclarativePropertyMap在运行期动态的创建这些结构化数据。

在QML中调用C++方法

QML中可以调用QObject及其派生类对象中的public slot的方法或标记为Q_INVOKABLE的方法。

上述的C++方法可以具有参数和返回值,QML支持下列数据类型:

   * bool
   * unsigned int, int
   * float, double, qreal
   * QString
   * QUrl
   * QColor
   * QDateQTimeQDateTime
   * QPointQPointF
   * QSize, QSizeF
   * QRectQRectF
   * QVariant

下面的例子演示了当MouseArea被点击时,触发“Stopwatch”对象的start()/stop():

// 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 QtQuick 1.0

 Rectangle {
     width: 300
     height: 300

     MouseArea {
         anchors.fill: parent
         onClicked: {
             if (stopwatch.isRunning())
                 stopwatch.stop()
             else
                 stopwatch.start();
         }
     }
 }

请注意,在这个特殊的例子中,有一个更好的方法来达到同样的结果——main.qml中可以用一个“运行中“属性(property),更漂亮的QML代码如下:

// main.qml
 import QtQuick 1.0

 Rectangle {
     MouseArea {
         anchors.fill: parent
         onClicked: stopwatch.running = !stopwatch.running
     }
 }

此外,还可以调用functions declared in QML from C++描述的方法。

网络组件(Network Components)

如果传递给QDeclarativeComponent一个网络资源,或者QML document中引用了网络资源,QDeclarativeComponent会在创建对象之前先获取网络资源数据。在这种情况下QDeclarativeComponent将有一个加载状态(Loadingstatus)。应用程序将一直等待(在调用QDeclarativeComponent::create()之前),直到组件准备完毕。

下面的例子演示了如何加载一个网络QML文件资源。QDeclarativeComponent创建后,先检查组件是否正在加载,如果正在加载则连接QDeclarativeComponent::statusChanged()信号,否则直接调用continueLoading()方法。虽然在这个例子里已经知道URL在远程,但这个检查还是必须的,这样可以在组件已经缓存了该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资源(Qt Resources)

QML可以通过qrc:URL从Qt资源系统(Qt Resource System)中加载,例如:

[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 QtQuick 1.0

 Image {
     source: "images/background.png"
 }

注意:QML中无法直接访问资源系统。如果主QML文件作为资源加载,主QML文件中的所有指定相对路径的文件都将从资源系统中加载。如果主QML文件没有作为资源加载,那么资源系统中的文件无法在QML中访问。

分享到:
评论

相关推荐

    QML与C++混合编程.pdf

    在QML中,向使用标准的item一样使用新定义的item 现举例说明,我们现尝试使用用Qt C++实现的MyButton对象(如下qml代码),它有自己的属性、方法以及信号的handler。用法如下(它与使用其它标准的QML item一样),...

    QML与C++交互使用

    我们知道 ,通过Qt Declarative module ,C++可以动态创建和操纵QML的组件(cpmponents) ,我们利用这些API使用C++来拓展我们的QML程序,反过来也可以将QML嵌入到你的C++程序中。通过Qt的元对象系统( Qt‘s meta...

    QML我们如何与C++一起使用.wps

    通过Qt Declarative module ,C++可以动态创建和操纵QML的组件(cpmponents) ,我们利用这些API使用C++来拓展我们的QML程序,反过来也可以将QML嵌入到你的C++程序中。通过Qt的元对象系统( Qt‘s metaobject system)...

    Qt6 QML Book/Qt C++/样板应用程序示例源码

    Qt6 QML Book/Qt C++/样板应用程序 示例源码 CSDN审核可能较慢,如无法下载,可以过段时间再回来看下 仅供相关爱好者交流使用,请于下载24小时内删除

    QML和OpenGL混合渲染(演示程序)

    此资源是演示程序,包含了Windows、Linux、MacOS X以及Android的演示程序,大家可以免...接下来的这篇文章讲的是我们使用QML,借助Qt库和OpenGL,实现了使用着色器定义OpenGL的渲染方式,为大家呈现混合渲染的效果。

    qml 软键盘 虚拟键盘

    qml程序在C++代码里面调用setAutoSipEnabled 不起作用 C++屏蔽focus事件 qml里实现了光标绘制

    QML_TCP.rar

    此资源使用的是qt5.12 ,可直接打开,工程就是使用tcp拉取视频流,使用ffmpeg解码,然后传到qml(自定义)中去渲染 由于基本不写博客,一些注意说明就在这里写了: 1、资源肯定能用,我自己做了3天出来的,但是一...

    qt-signal-slot:使用信号和槽将 QML 连接到 C++

    它通过在 QML 中嵌入 C++ 代码作为上下文属性而不是显式连接信号和槽来实现这一点。 当程序启动时,C++ 部分向 QML 发送一个信号,包括一个参数。 该信号仅发送一次。 当用户点击窗口区域时,一个信号从 QML 发送到...

    使用Qt C++和OpenCV获取和显示实时RTSP视频流

    本资源介绍了如何在Qt C++应用程序中使用OpenCV库来获取实时RTSP视频流,并将其显示在QML界面中。通过这种方式,你可以创建一个实时视频监控应用程序或其他需要实时视频流的应用程序。该资源提供了完整的代码示例和...

    QmlBook中文版.rar

    一本很不错的QML书,教程将介绍使用Qt5.x版本开发应用程序的相关技术。教程更侧重讲解新的Qt Quick 开发技巧,在讲解Qt Quick扩展内容时会涉及部分Qt C++内容

    node.qml:Node.js 到 QML 的端口

    潜在地,QML 应用程序应该能够使用大多数 Node.js 库。 不支持 Node.js C++ 插件。 该项目处于 Work-In-Progress 状态,尚未准备好进行任何实际使用。路线图可用。建筑学Node.qml 由以下组件组成: C++ 库- 提供将 ...

    QML与C++交互

    Qt Quick 是一种高级用户界面技术,使用它可轻松地创建供移动和嵌入式设备使用的动态触摸式界面和轻量级应用程序。三种全新的技术共同构成了 Qt Quick 用户界面创建工具包:一个改进的Qt Creator IDE、一种新增的...

    补天云QT工具箱QML源码保护隐藏工具-应用实例源码V0.1

    应用实例的C++ QT源码。...在使用补天云QML源码保护工具之后,使得编译后的QML应用程序的可执行文件中在不包含QML和JavaScript源码的明文形式的前提下,QML应用仍然能够正常运行。 操作介绍技术文章: ...

    福优林@Qt5小白变大牛初级篇word---第11章.pdf

    也就是说,使用 Qt 5,我们不仅可以使用 C++ 开发 Qt 程序,而且可以使用 QML。 虽然 QML 是解释型语言,性能要比 C++ 低一些,但是新版 QML 使用 V8,Qt 5.2 又引入了专为 QML 优化的 V4 引擎,使得其性能不再有...

    Qt中文帮助文档

    使用QtDeclarative C++模块可以从你的QT 应用程序中载入QML文件并与之互动。 QML是对JavaScript一种扩展,它提供一种机制使用QML元素来说明构建一个对象树。QML对 JavaScript与Qt现有的QObjec -tbase类型系统进行...

    使用QML进行界面开发

    QML是Qt提供的一种描述性的脚本语言,类似于CSS(CascadingStyleSheets),可以在脚本里创建图形对象,并且支持各种图形特效,以及状态机等,同时又能跟Qt写的C++代码进行方便的交互,使用起来非常方便。采用Q

    clipboard:Go剪贴板(go-qml应用程序,使用Qt)

    使用Qt的功能将文本存储在剪贴板中或从剪贴板中加载或加载文本。 该分支使用qml.Common来调用QClipboard包装器。 这种方法(比 )要慢一点,但是代码要干净得多,而且往往更安全。 安装: 请参阅go-qml的。 如果...

    Qt5.8中QML教程并结合实际工程项目详解

    这篇博客会介绍一下Qt中使用QML来设计GUI界面,以及QML与C++交互的方式。QML是Qt自定义的一种GUI描述文件,其文档结构有点类似NodeJS或者TypeScript,跟Android编程中的Activity的设计也很类似,在客户端GUI编程的...

Global site tag (gtag.js) - Google Analytics