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

相關文章
相關標籤/搜索