C++程序中使用QML绑定机制

来源:互联网 发布:校园网mac绑定错误 编辑:程序博客网 时间:2024/04/28 15:57
原文地址:http://doc.qt.digia.com/4.7-snapshot/qtbinding.html
QML被定为一种可容易使用C++扩展,并可扩展C++的语言.使用Qt Declarative模块中的类可在C++中加载和操作QML中的组件,通过Qt的元对象系统,QML和C++对象可轻易的使用信号和槽机制进行通信.此外,QML插件可以创建发布可重用QML组件.

你可能有很多种理由要将QML和C++混合使用.如:

  • 使用C++源码中的函数/功能 (如使用基于Qt的C++数据模型,或调用三方C++库中的函数)
  • 访问Qt Declarative模块中的函数/功能 (如使用QDeclarativeImageProvider动态创建图像)
  • 创建QML组件(用于自己的项目或发布给其他人使用)

要使用Qt Declarative模块,必须包含和链接相应的模块,请见module index page.Qt Declarative UI Runtime 文档展示如何使用这个模块创建基于C++的应用程序.

核心模块类

Qt Declarative模块提供了一组C++ API用于在C++中扩展QML应用程序,并可将QML嵌入到C++应用程序中.Qt Declarative模块中有几个核心类为实现这个目标提供了必要的支持:

  • QDeclarativeEngine: QML引擎提供了运行QML的环境.每个应用程序都需要至少一个引擎实例.
  • QDeclarativeComponent:一个组件封装了一个QML文档(QML document).
  • QDeclarativeContext: 上下文用来使应用程序向引擎创建的QML组件暴露数据.

 QDeclarativeEngine 用来为其中的所有QML组件实例配置全局选项:如用于网络通信的QNetworkAccessManager 和用于持久化存储的文件路径等.

QDeclarativeComponent 用于加载QML文档.每个QDeclarativeComponent 实例代表一个单一文档.组件可使用代表QML文档的URL或文件路径,QML代码来创建.组件实例化是通过QDeclarativeComponent::create()方法完成的,如下所示:

 QDeclarativeEngine engine;
 QDeclarativeComponent component(&engine, QUrl::fromLocalFile("MyRectangle.qml"));
 QObject *rectangleInstance = component.create();

 // ...
 delete rectangleInstance;

QML文档也可使用QDeclarativeView来加载.这个类为基于QWidget的视图加载QML组件提供了方便.(向基于QWidget的应用程序中整合QML的其他方法请见Integrating QML Code with existing Qt UI code)

QML与C++结合的方式

使用C++扩展QML应用程序有很多种方式.例如::

  • 在C++中加载QML组件并进行操作(可操作其子元素)
  • 直接将C++对象及其属性嵌入到QML组件中(例如,在QML中调用指定的C++对象,或使用数据集来模拟一个列表模型)
  • 定义新的QML元素(QObject继承)并可在QML代码中直接创建

这些方式在下面做展示.当然这些方式相互间不冲突,在应用程序中可根据需要组合使用.

在C++中加载QML组件

QML文档可使用QDeclarativeComponent 或QDeclarativeView来加载.QDeclarativeComponent 将QML组件作为一个C++对象加载;QDeclarativeView 也是这样的,但他将QML组件直接加载到一个QGraphicsView中. 可方便的将QML组件加载到一个基于QWidget应用程序中.

例如,有如下所示的一个MyItem.qml文件:

 import QtQuick 1.0

 Item {
     width: 100; height: 100
 }

下面的C++代码将这个QML文档加载到QDeclarativeComponent 或QDeclarativeView .使用QDeclarativeComponent 需要调用QDeclarativeComponent::create()来创建一个新的组件实例,而QDeclarativeView 自动创建组件实例,可通过QDeclarativeView::rootObject()来访问:

// Using QDeclarativeComponent QDeclarativeEngine engine; QDeclarativeComponent component(&engine,         QUrl::fromLocalFile("MyItem.qml")); QObject *object = component.create(); ... delete object; 
 // Using QDeclarativeView QDeclarativeView view; view.setSource(QUrl::fromLocalFile("MyItem.qml")); view.show(); QObject *object = view.rootObject();

这样就创建了一个MyItem.qml组件的实例--object.可使用QObject::setProperty() 或QDeclarativeProperty修改项目的属性:

 object->setProperty("width", 500);
 QDeclarativeProperty(object, "width").write(500);

当然,也可将对象转换为其实际类型,以便于在编译时期安全的调用方法.本例中基于MyItem.qml的对象是一个Item,由QDeclarativeItem 类来定义:

 QDeclarativeItem *item = qobject_cast<QDeclarativeItem*>(object);
 item->setWidth(500);

也可使用QMetaObject::invokeMethod() 和QObject::connect()来连接或调用定义在组件中的信号或函数.更多信息见Exchanging data between QML and C++ .

定位子对象

QML组件本质上是一个具有兄弟和子节点的对象树.可使用QObject::findChild()传递一个对象名称获取QML组件的子对象.例如MyItem.qml中的根对象具有一个Rectangle子元素:

 import QtQuick 1.0

 Item {
     width: 100; height: 100

     Rectangle {
         anchors.fill: parent
         objectName: "rect"
     }
 }

可这样获取子对象:

 QObject *rect = object->findChild<QObject*>("rect");
 if (rect)
     rect->setProperty("color", "red");

如果objectName被用于ListView,Repeater代理,或其他生成多个实例的代理上,将会有多个子对象具有相同的名称(objectName).这时,使用QObject::findChildren()获取所有叫做objectName的子元素.

警告: 由于这种方法可以在C++中获取并操作对象树中内部的QML元素,除了测试和建立原型外我们不建议采用这种方式.QML和C++整合在一起的一个优势就是将QML的用户界面与C++逻辑和数据集相隔离,如果在C++中直接获取并操作QML对象中的内部组件会打破这个策略. 这将使开发变得困难,如更改了QML视图,新的组件中不含objectName子元素,会发生错误.最好的情况是C++实现对QML用户界面实现和内部组成QML对象树不做任何假设.

在QML组件中嵌入C++对象

当在C++应用程序中加载QML场景时,将C++数据嵌入到QML对象中是很有帮助的.QDeclarativeContext 可以向QML组件暴漏数据,将数据从C++注入到QML中.

例如,下面的QML项中有一个currentDateTime值,但并没有在这个上下文中声明:

 // MyItem.qml
 import QtQuick 1.0

 Text { text: currentDateTime }

这个currentDateTime值可以直接由加载QML组件的C++应用程序使用QDeclarativeContext::setContextProperty()进行设置:

 QDeclarativeView view;
 view.rootContext()->setContextProperty("currentDateTime", QDateTime::currentDateTime());
 view.setSource(QUrl::fromLocalFile("MyItem.qml"));
 view.show();

上下文属性可以存储为QVariant或者QObject*类型.这意味着自定义的C++对象也可以使用这种方式注入,而且可以直接在QML中读取或修改这些对象.我们将上例中的QDateTime值修改为一个嵌入的QObject实例,让QML代码调用对象实例的方法:

class ApplicationData : public QObject {     Q_OBJECT public:     Q_INVOKABLE QDateTime getCurrentDateTime() const {         return QDateTime::currentDateTime();     } }; int main(int argc, char *argv[]) {     QApplication app(argc, argv);     QDeclarativeView view;     ApplicationData data;     view.rootContext()->setContextProperty("applicationData", &data);     view.setSource(QUrl::fromLocalFile("MyItem.qml"));     view.show();     return app.exec(); } 

// MyItem.qmlimport QtQuick 1.0Text { text: applicationData.getCurrentDateTime() }
(注意C++向QML返回的date/time值可使用Qt.formatDateTime() 及相关函数进行格式化.)

如果QML需要接收上下文的信号,可使用Connections元素进行连接.例如,如果ApplicationData有一个叫做dataChanged()的信号,这个信号可以使用Connections对象连接到一个信号处理器上:

 Text {     text: applicationData.getCurrentDateTime()     Connections {         target: applicationData         onDataChanged: console.log("The application data changed!")     } }

上下文属性在QML视图中使用基于C++的数据模型时很有用.见String ListModel,Object ListModel 和 AbstractItemModel 模型,展示了在QML视图中使用QStringListModel模型,基于QObjectList的模型 和QAbstractItemModel模型 .

更多信息见QDeclarativeContext .

定义新的QML元素

QML中可以定义新的QML元素,同样也可在C++中定义;事实上很多QML元素都是通过C++类实现的.当使用这些元素创建一个QML对象时,只是简单的创建了这个基于QObject的C++类的实例,并设置了属性.

要创建与Qt Quick元素兼容的项,需要使用QDeclarativeItem作为基类.然后实现自绘和像其他QGraphicsObject一样的功能.注意在QDeclarativeItem中默认设置了QGraphicsItem::ItemHasNoContents,因为其不绘制任何东西;如果项目需要绘制则需要清除这个标志(相反的情况是只作为输入处理和逻辑分组的情况).

例如,下面是一个带有image属性的ImageViewer类:

 #include <QtCore> #include <QtDeclarative> class ImageViewer : public QDeclarativeItem {     Q_OBJECT     Q_PROPERTY(QUrl image READ image WRITE setImage NOTIFY imageChanged) public:     void setImage(const QUrl &url);     QUrl image() const; signals:     void imageChanged(); };

除了从QDeclarativeItem继承外,这都可作为与QML无关的常规类.然而,使用qmlRegisterType()注册到QML引擎后:

qmlRegisterType<ImageViewer>("MyLibrary", 1, 0, "ImageViewer");

加载到C++应用程序或插件中的QML代码就可以操作ImageViewer对象:

import MyLibrary 1.0ImageViewer { image: "smile.png" }

这里建议不要使用QDeclarativeItem文档指定属性之外的功能.这是因为GraphicsView后台依赖QML的实现细节,因此QtQuick项可再向底层移动,在QML角度上可以应用但不能修改.要最小化自定义可视项的可移植要求,就应尽量坚持使用QDeclarativeItem文档标记的属性.从QDeclarativeItem中继承但没有文档化的属性都是与实现细节相关的;他们不受官方支持可能在相关的发布版本中被去掉.

注意自定义的C++类不必从QDeclarativeItem继承;只有在需要显示时才是必须的.如果项不可见,可从QObject继承.

创建QML元素的更多信息,见Writing QML extensions with C++ 和Extending QML Functionalities using C++ .

在QML和C++之间交换数据

QML和C++对象之间可通过信号槽,属性修改等机制进行通信.对于一个C++对象,任何暴露在Qt的元对象系统中的数据--属性,信号,槽和使用Q_INVOKABLE标记的方法都可在QML中访问.在QML端,所有QML对象的数据都可在Qt元对象系统和C++中访问.

调用函数

QML函数可在C++中调用,反之亦然.

所有的QML函数都被暴漏在了元数据系统中,并可通过QMetaObject::invokeMethod()调用.C++应用程序调用QML函数:

// MyItem.qml import QtQuick 1.0 Item {     function myQmlFunction(msg) {         console.log("Got message:", msg)         return "some return value"     } }

 
 // main.cpp QDeclarativeEngine engine; QDeclarativeComponent component(&engine, "MyItem.qml"); QObject *object = component.create(); QVariant returnedValue; QVariant msg = "Hello from C++"; QMetaObject::invokeMethod(object, "myQmlFunction",         Q_RETURN_ARG(QVariant, returnedValue),         Q_ARG(QVariant, msg)); qDebug() << "QML function returned:" << returnedValue.toString(); delete object;

注意QMetaObject::invokeMethod()中Q_RETURN_ARG() 和Q_ARG()的参数必须指定为QVariant类型,这是QML函数和返回值的通用数据类型.

在QML中调用C++函数,函数必须是Qt的槽或标记了Q_INVOKABLE宏的函数,才能在QML中访问.下面范例中,QML代码调用了(使用QDeclarativeContext::setContextProperty()设置到QML中的)myObject对象的方法:

 // MyItem.qml import QtQuick 1.0 Item {     width: 100; height: 100     MouseArea {         anchors.fill: parent         onClicked: {             myObject.cppMethod("Hello from QML")             myObject.cppSlot(12345)         }     } }

 class MyClass : public QObject {     Q_OBJECT public:     Q_INVOKABLE void cppMethod(const QString &msg) {         qDebug() << "Called the C++ method with" << msg;     } public slots:     void cppSlot(int number) {         qDebug() << "Called the C++ slot with" << number;     } }; int main(int argc, char *argv[]) {     QApplication app(argc, argv);     QDeclarativeView view;     MyClass myClass;     view.rootContext()->setContextProperty("myObject", &myClass);     view.setSource(QUrl::fromLocalFile("MyItem.qml"));     view.show();     return app.exec(); }

QML支持调用C++的重载函数.如果C++中有多个同名不同参的函数,将根据参数数量和类型调用正确的函数.

接收信号

所有QML信号都可在C++中访问,像任何标准的Qt C++信号一样可使用QObject::connect()进行连接.相反,任何C++信号都可被QML对象的信号处理函数接收.

下面的QML组件具有一个叫做qmlSignal的信号.这个信号使用QObject::connect()连接到了一个C++对象的槽上,当qmlSignal触发时会调用cppSlot()函数:

 // MyItem.qml import QtQuick 1.0 Item {     id: item     width: 100; height: 100     signal qmlSignal(string msg)     MouseArea {         anchors.fill: parent         onClicked: item.qmlSignal("Hello from QML")     } }

 class MyClass : public QObject {     Q_OBJECT public slots:     void cppSlot(const QString &msg) {         qDebug() << "Called the C++ slot with message:" << msg;     } }; int main(int argc, char *argv[]) {     QApplication app(argc, argv);     QDeclarativeView view(QUrl::fromLocalFile("MyItem.qml"));     QObject *item = view.rootObject();     MyClass myClass;     QObject::connect(item, SIGNAL(qmlSignal(QString)),                      &myClass, SLOT(cppSlot(QString)));     view.show();     return app.exec(); }

要在QML中连接Qt C++的信号,使用on<SignalName>语法访问信号句柄.如果C++对象可直接在QML中创建(见上面的Defining new QML elements),信号处理函数可在对象定义时指定.在下面例子中,QML代码创建了一个ImageViewer对象,C++对象的imageChanged和loadingError信号连接到QML中的onImageChanged和onLoadingError信号处理函数:

 ImageViewer {     onImageChanged: console.log("Image changed!")     onLoadingError: console.log("Image failed to load:", errorMsg) }

 class ImageViewer : public QDeclarativeItem {     Q_OBJECT     Q_PROPERTY(QUrl image READ image WRITE setImage NOTIFY imageChanged) public:     ... signals:     void imageChanged();     void loadingError(const QString &errorMsg); };

(注意如果信号被声明为属性的NOTIFY信号,QML就允许使用on<Property>Changed句柄访问这个信号,即使信号的名称不是<Property>Changed.上例中,如果将imageChanged信号改为imageModified,onImageChanged信号处理函数还是会被调用的.)

然而对于不是从QML中创建的对象,QML中的元素只能访问已创建的对象--例如如果对象是通过QDeclarativeContext::setContextProperty()设置的--就可使用Connections元素来设置信号处理函数了:

// MyItem.qml import QtQuick 1.0 Item {     Connections {         target: imageViewer         onImageChanged: console.log("Image has changed!")     } }

 ImageViewer viewer; QDeclarativeView view; view.rootContext()->setContextProperty("imageViewer", &viewer); view.setSource(QUrl::fromLocalFile("MyItem.qml")); view.show();
 

C++信号可以使用枚举值作为参数,枚举定义在类中随信号触发而传递,这个枚举必须使用Q_ENUMS宏注册.见Using enumerations of a custom type.

修改属性

C ++中可以访问QML对象的所有属性.对如下QML对象:

 // MyItem.qml import QtQuick 1.0 Item {     property int someNumber: 100 }

使用QDeclarativeProperty, 或QObject::setProperty() 和QObject::property()可以设置和读取someNumber属性:

 QDeclarativeEngine engine; QDeclarativeComponent component(&engine, "MyItem.qml"); QObject *object = component.create(); qDebug() << "Property value:" << QDeclarativeProperty::read(object, "someNumber").toInt(); QDeclarativeProperty::write(object, "someNumber", 5000); qDebug() << "Property value:" << object->property("someNumber").toInt(); object->setProperty("someNumber", 100);

你应该总使用QObject::setProperty(),QDeclarativeProperty 或QMetaProperty::write()修改QML属性值,使QML引擎知道属性已经被修改.例如,假设有一个自定义的元素PushButton,带有一个buttonText属性,反映内部的m_buttonText成员变量值.直接修改成员变量值是不明智的:

 // BAD! QDeclarativeComponent component(engine, "MyButton.qml"); PushButton *button = qobject_cast<PushButton*>(component.create()); button->m_buttonText = "Click me";

由于直接修改了成员变量的值,越过了Qt的元对象系统,QML引擎就无法知道值被修改过.这样绑定到buttonText的属性就不会更新,任何onButtonTextChanged处理函数都不会被调用.

任何使用Q_PROPERTY宏声明的Qt属性都可在QML中访问.下面修改本文档前面例子,ApplicationData类具有一个backgroundColor属性.这个属性可在QML中进行读写:

// MyItem.qml import QtQuick 1.0 Rectangle {     width: 100; height: 100     color: applicationData.backgroundColor     MouseArea {         anchors.fill: parent         onClicked: applicationData.backgroundColor = "red"     } }

 class ApplicationData : public QObject {     Q_OBJECT     Q_PROPERTY(QColor backgroundColor             READ backgroundColor             WRITE setBackgroundColor             NOTIFY backgroundColorChanged) public:     void setBackgroundColor(const QColor &c) {         if (c != m_color) {             m_color = c;             emit backgroundColorChanged();         }     }     QColor backgroundColor() const {         return m_color;     } signals:     void backgroundColorChanged(); private:     QColor m_color; };
 

注意backgroundColorChanged被标记为backgroundColor属性的NOTIFY信号.如果Qt属性没有相关的NOTIFY信号,属性就不能用于QML的属性绑定,因为当属性值被修改时QML引擎不会得到通知.如果在QML中使用自定义类型,确保属性具有NOTIFY信号,以便于用于属性绑定中.

在QML中使用QML属性的更多信息见Tutorial: Writing QML extensions with C++ .

支持的数据类型

用于QML中的任何C++数据--自定义属性,或信号和函数的参数,QML都必须支持其类型.

默认QML支持如下数据类型:

  • bool
  • unsigned int, int
  • float, double, qreal
  • QString
  • QUrl
  • QColor
  • QDate, QTime, QDateTime
  • QPoint, QPointF
  • QSize, QSizeF
  • QRect, QRectF
  • QVariant
  • QVariantList,QVariantMap
  • QObject*
  • 由Q_ENUMS()声明的枚举类型

为了可以在QML创建和使用自定义C++类型,C++类必须使用qmlRegisterType()注册为QML类型,请见上面的Defining new QML elements 小节.

JavaScript数组和对象

QML内建支持在QVariantList和JavaScript数组之间,QVariantMap和JavaScript对象间的转换.

例如,如下定义在QML中的函数需要两个参数,一个数组一个对象,使用标准的JavaScript语法访问数组和对象输出其中的内容.C++代码调用了这个函数,传递QVariantList 和QVariantMap参数,将自动转换为JavaScript的数组和对象:

 // MyItem.qml Item {     function readValues(anArray, anObject) {         for (var i=0; i<anArray.length; i++)             console.log("Array item:", anArray[i])         for (var prop in anObject) {             console.log("Object item:", prop, "=", anObject[prop])         }     } }

 // C++ QDeclarativeView view(QUrl::fromLocalFile("MyItem.qml")); QVariantList list; list << 10 << Qt::green << "bottles"; QVariantMap map; map.insert("language", "QML"); map.insert("released", QDate(2010, 9, 21)); QMetaObject::invokeMethod(view.rootObject(), "readValues",         Q_ARG(QVariant, QVariant::fromValue(list)),         Q_ARG(QVariant, QVariant::fromValue(map)));

This produces output like:

 Array item: 10 Array item: #00ff00 Array item: bottles Object item: language = QML Object item: released = Tue Sep 21 2010 00:00:00 GMT+1000 (EST)

同样,如果C++定义了QVariantList 或QVariantMap 类型的属性或函数参数,在QML访问时,可创建JavaScript的数组或对象,并自动被转换为QVariantList 或QVariantMap 传递给C++.

使用自定义枚举类型

要在自定义C++组件中使用枚举,枚举类型必须使用Q_ENUMS宏注册到Qt的元对象系统.例如,如下C++类型具有一个Status枚举类型:

 class ImageViewer : public QDeclarativeItem {     Q_OBJECT     Q_ENUMS(Status)     Q_PROPERTY(Status status READ status NOTIFY statusChanged) public:     enum Status {         Ready,         Loading,         Error     };     Status status() const; signals:     void statusChanged(); };

假设ImageViewer类已经使用qmlRegisterType()进行注册,现在其Status枚举可用在QML中:

 ImageViewer {     onStatusChanged: {         if (status == ImageViewer.Ready)             console.log("Image viewer is ready!")     } }

要使用内置的枚举,C++类必须注册到QML中.如果C++类型不可实例化,可使用qmlRegisterUncreatableType()注册.在QML中枚举值其首字母必须大写.

更多信息见Writing QML extensions with C++ 和Extending QML Functionalities using C++.

枚举值作为信号参数

C++信号可以向QML中传递一个枚举类型参数,假设枚举和信号定义在同一个类中,或枚举值定义在Qt命名空间(Qt Namespace)中.

此外,如果C++信号带有一个枚举参数,应该使用connect()函数与QML中的函数相关联,枚举类型必须使用qRegisterMetaType()注册.

对于QML信号,作为信号参数的枚举值使用int类型替代:

 ImageViewer {     signal someOtherSignal(int statusValue)     Component.onCompleted: {         someOtherSignal(ImageViewer.Loading)     } }

从字符串做自动类型转换

为了方便,在QML中一些基本类型的值可使用格式化字符串指定,便于在QML中向C++传递简单的值.

TypeString formatExampleQColor颜色名称, "#RRGGBB", "#RRGGBBAA""red", "#ff0000", "#ff000000"QDate"YYYY-MM-DD""2010-05-31"QPoint"x,y""10,20"QRect"x,y,宽x高""50,50,100x100"QSize"宽x高""100x200"QTime"hh:mm:ss""14:22:55"QUrlURL字符串"http://www.example.com"QVector3D"x,y,z""0,1,0"枚举值枚举值名称"AlignRight"

(更多字符串格式和类型见basic type documentation.)

这些字符串格式用于设置QML属性值和向C++函数传递参数.本文档中有很多范例进行演示;在上面的范例中,ApplicationData类有一个QColor类型的backgroundColor属性,在QML中使用字符串"red"而不是一个QColor对象进行赋值.

如果喜欢使用显式类型赋值,Qt对象提供了便利的全局函数来创建对象的值.例如Qt.rgba()创建一个基于RGBA的QColor值.这个函数返回的QColor类型的值可用于设置QColor类型的属性,或调用需要QColor类型参数的C++函数.

创建QML插件

Qt Declarative模块包含一个QDeclarativeExtensionPlugin类,这个抽象类用于创建QML插件.可在QML应用程序中动态加载QML扩展类型.

更多信息见QDeclarativeExtensionPlugin 文档和How to Create Qt Plugins .

使用Qt资源系统管理资源文件

Qt resource system 可将资源文件存储在二进制可执行文件中.这对创建QML/C++联合的应用程序很有帮助,可通过资源系统的URI(像其他图片和声音资源文件一样)调度访问QML文件,而不是使用相对或绝对文件系统路径.注意如果使用资源系统,当QML资源文件被修改后必须重新编译可执行应用程序,以便于更新包中的资源.

要在QML/C++应用程序中使用资源系统:

  • 创建一个.qrc资源集合文件,以XML格式例举资源文件
  • 在C++中,使用:/prefix或qrc调度URL加载主QML文件资源

这样做后,QML中所有已相对路径指定的文件都从资源文件中加载.使用资源系统完全对QML层透明;即QML代码可以用相对路径来访问资源文件,而不带有qrc调度.这个调度(qrc)只用于在C++中引用资源文件.

这是使用Qt资源系统的应用程序包.目录结构如下:

 project     |- example.qrc     |- main.qml     |- images         |- background.png     |- main.cpp     |- project.pro

main.qmlbackground.png 文件作为资源文件打包.这在example.qrc资源文件中指定:

 <!DOCTYPE RCC> <RCC version="1.0"> <qresource prefix="/">     <file>main.qml</file>     <file>images/background.png</file> </qresource> </RCC>

由于background.png 是一个资源文件,main.qml可在example.qrc中使用的相当路径引用它:

 // main.qml import QtQuick 1.0 Image { source: "images/background.png" }

要使QML文件正确的定位资源文件,main.cpp加载主QML文件--main.qml,访问资源文件需要使用qrc调度(scheme):

 int main(int argc, char *argv[]) {     QApplication app(argc, argv);     QDeclarativeView view;     view.setSource(QUrl("qrc:/main.qml"));     view.show();     return app.exec(); }

最后在project.pro中将RESOURCES 变量设置为用来构建应用程序资源的example.qrc 文件:

 QT += declarative SOURCES += main.cpp RESOURCES += example.qrc
原创粉丝点击