QtQuick 中的 qml 与 Qt 的 C++

QtQuick 可使用内置的 JavaScript 引擎加载相应的 JS 代码,使用起来特别方便。c++

在 Qt 中使用 C++ 开发底层,QtQuick 用来加载、处理图像,而后使用 Qt 提供的接口保证二者可以正常通讯便可。git

 

1. 首先用Qt Creator新建项目,选择Qt Quick Controls 2 Application,命名项目…github

2. 在资源文件qml.qrc中添加一个qml文件,命名…app

3. 在qml文件中输入相应的元素(Item,Rectanger,Image,Canvas等等)。函数

1 import QtQuick 2.0
2 import QtQuick.Window 2.2
3 
4 Window {
5     width: 800
6     height: 600
7     visible: true
8     title: "Test window"
9 }

这里仅用了一个 Window 元素,加载后只显示一个空白的窗体。ui

4. 在main函数中加载qml引擎须要用到QQmlApplicationEngine类,经过该类加载qml文件。以下:this

 1 int main(int argc, char *argv[])
 2 {
 3     QGuiApplication app(argc, argv);
 4 
 5     QQmlApplicationEngine engine;
 6     engine.load(QUrl(QStringLiteral("qrc:/Test.qml"))); 7 
 8     return app.exec();
 9 }

其中,engine 对象的 load() 方法,须要一个QUrl对象提供qml文件的url路径,这里加载了一个qml文件,即“Test.qml”文件。url

运行以后获得空白的窗体。若是想要显示不一样的内容,须要在qml文件中添加相应的元素或本身编写控件再添加。spa

 

用 QQmlApplicationEngine 加载的 qml 文件可使用 QML 的 Window 控件。指针

可是在c++ 的类方法中没法直接使用 QQmlApplicationEngine 类,若使用该类加载 qml 文件,会致使在触发显示窗口事件时,窗口显示一下当即消失,可是程序依然在运行,所以就没法对qml窗口进行操做。

 

1 void Data::view() {
2         QQmlApplicationEngine engine;
3         engine.load(QUrl(QStringLiteral("qrc:/Test.qml")));
4 }

在Data类的view()方法中使用 QQmlApplicationEngine load() 方法没法正常显示窗口。

 

 那么,如何在方法中调用加载 qml 文件呢?

 

要在 c++ 文件中显示qml文件的内容,Qt 提供了 QQuickView 类(QtQuick1.0则是使用 QDeclaritiveView 类,可是该类在加载 qml 文件时,响应缓慢)使用 QQuickView 便可加载 qml 并显示内容。

 1 void Data::view() {
 2     QQuickView *compassview = new QQuickView;
 3     compassview->setSource(QUrl(QStringLiteral("qrc:/Compass.qml")));
 4 //    compassview->rootContext()->setContextProperty("dataRadius", this);
 5     QQmlContext *context = compassview->rootContext();
 6     context->setContextProperty("dataSource", this);
 7     // 设置窗口图标
 8     QIcon icon = QIcon(QStringLiteral(":/img/compass.ico"));
 9     compassview->setIcon(icon);
10 //    compassview->set
11     // 设置窗口缩放时,根对象也会随之缩放
12     compassview->setResizeMode(QQuickView::SizeRootObjectToView);
13     compassview->setTitle("Compass heading pitch & roll");
14     compassview->show();
15 
16 }

compassview 指向一个 QQuickView 对象,setSource() 方法指定该 QQuickView 对象所要加载的qml文件。

而 compassview->rootContext() 则是获取对象的根元素上下文,而后用 context 对象的 setContextProperty(const QString *, const QVariant*) 方法设定上下文属性,便可经过 QVariant 指针从 C++ 向 QML 传递数据。

 

然而若是qml文件是以 Window 做为根元素的话,QQuickView加载时会出现一个警告,由于QQuickView继承自QQuickWindow(又继承自QWindow),它自己就是一个窗口类,若是再用 QML 的 Window 控件做为根元素,天然会出现警告,能够忽略掉该警告,也能够将 Window 改为 Item (但要注意,Window 的有些属性在 Item 中不存在),这样就不会出现警告了。 

 

而后在 qml 文件中经过设定一个定时器 Timer,能够定时从 c++ 中获取数据。

 1     /*
 2      * 设置一个定时器,每隔 500ms 就从数据源中读取数据,修正图像
 3     */
 4     Timer {
 5         id: updateTimer
 6         interval: 500
 7         running: true
 8         repeat: true
 9 
10         onTriggered: {
11 //            console.log("Timer is triggered! ")
12 //            var data = DataSource.getData();
13             var data = dataSource.getRadius()
14 
15             data = [0, 0, 0]
16 //            h_refresh(data[0])
17             refresh(data[0], data[1], data[2])
18         }
19     }

qml中 dataSource 须要与上面的 setContextProperty(“dataSource”, this) 语句中的 dataSource 同名(这样就能够直接调用相关对象的方法,好比 getRadius() 方法),不然 qml 将没法获取数据。

 

C++ 中设置 QQuickView 的窗口图标、标题等等与 QWindow 相似。

compassview->setResizeMode(QQuickView::SizeRootObjectToView) 设置了根对象大小随窗口大小改变而改变。这样就能动态缩放qml内容。

 

--------------------------------------------------------------------------------

另外须要注意的是,若是先用 Qt 新建了一个 Qt 应用,想要再添加 qml 文件并运行,须要修改项目的 .pro 文件,添加如下内容:

QT += qml quick

这样,在编译时才不会出错。

 

====================================================

另外,附上完整的代码

https://github.com/GitFuture/Compass

相关文章
相关标签/搜索