2015年6月20日 星期六

[Qt] 003 - QML 與Qt Quick


QML 與 Qt Quick

QML

這篇文章我們要來了解一下什麼是QML,QML的全名是Qt Markup Language,是Qt官方開發出來的一種描述使用者介面的語言,於Qt 4.6時所發布。在Qt 4.6以前,Qt在使用者介面的建構方式類似於大多數框架(如Android)的原理,其檔案為附檔名".ui"的檔案,它是一種自定義的XML檔案,透過對應模組的解析,讓底層依照檔案內的定義值繪製圖形(如Button)在頁面上。

這樣的建構方式,對程式開發人員而言,要花不少的時間在調整UI的大小或位置,而QML的設計目的,就是希望語法簡單明瞭,讓UI設計人員也可以輕易學習,省去協同開發上所耗費的整合時間。從QML的語法看起來,有點類似CSS的樣子,同時又支援JavaScript作為其程式邏輯的部分,相信對於稍微有些邏輯概念、但無任何程式語言開發基礎的對象,應該是能輕易理解且上手的。

QML本身是一種結構化的描述式語言,概念上與易懂的HTML類似,所謂的描述式語言就是透過簡單易懂的語法來描述畫面上的元件(包括UI與非UI元件),我們以上一篇文章所看到的QML檔案來做講解,下圖右是呈現的畫面,左邊則是程式碼的部分

這段程式碼引用(import)了QtQuick 2.2跟QtQuick.Window 2.1兩個模組
程式碼描述了畫面中有一個Window,該Window是可見的(visible: true),其寬(width)和高(height)都是360(Pixels)
在這個Window中有一塊MouseArea用來偵測滑鼠事件,該滑鼠區塊佔滿整個父物件(anchors.fill: parent),父物件即Window,當MouseArea中的onClicked(單擊)事件發生時離開程式(Qt.quit();)
另外,Window中還有一個文字區塊(Text),這個文字區塊顯示的文字是"Hello World"(前面加上的qsTr()函式是用來做翻譯檔使用的,之後會另闢文章說明),這個文字區塊置於父物件的中央(anchors.centerIn: parent)
很簡單吧!?利用簡單易懂的文字就可以描述這整個畫面的組成與互動行為。


我們簡單的來改寫一下這個QML檔,看一下執行的畫面有甚麼改變,首先如下圖改寫第17行並加入第18~20行的程式碼,執行畫面如下圖右。這幾行就是針對文字的部分,將其顯示文字改為"Hello QtQuick2",並更改其字體大小(36 pixels),且加上粗體(font.bold: true)與顏色(color: "blue")。


到此為止應該都還非常簡單明瞭,再稍微改寫一下,這次針對MouseArea的部分,我們看到程式碼在onClicked事件中,再次改掉字的顏色("#FF0000",即紅色)與內容(qsTr("Dobule click to quit")),然後把原本離開程式(Qt.quit();)的部分改放置於雙擊(onDoubleClicked)事件中。


好的,QML先介紹到此為止,下一篇文章會再繼續針對QML語法與組成方式的部分做進一步介紹。


Qt Quick

首先,先釐清一下兩個名詞的關係,QML與Qt Quick,很多人會把這兩個名詞混淆,或者說QML就等於Qt Quick,這樣的說法以比較寬鬆的角度來看或許是對的,但嚴格來說是不一樣的。我舉一個例子,相信大家就能明瞭它們的關係。各位應該都知道JavaScript吧!?那如果對Web開發有點經驗的話,應該也聽過甚至使用過jQuery,它們的關係是什麼?JavaScript是一種"語言",而jQuery是採用JavaScript這種語言寫成的一種"框架",這樣說明應該很清楚吧!?

沒錯,以此類推,QML是一種語言,Qt Quick是採用QML這種語言寫成的一種"框架",我們可以視為Qt Quick就是一堆QML物件的集成,我們也可以自行定義並集成一些QML物件,讓它變成一個模組(或稱套件)來使用。

剛才看到的程式碼中,引用了兩個QML模組,分別是QtQuick 2.2與QtQuick.Window 2.1,我們試著把第二行註解掉(QML的註解與C/C++相同,單行用"//",多行用"/* ... */"),可看到原本Window文字呈現黑色,且文字下方有紅色的錯誤提示,表示Qt Creator無法解析該QML物件(Window),因該物件是屬於QtQuick.Window 2.1這個模組中的,被我們註解掉,在沒有引入該模組的情況下,自然無法解析。若強行編譯並執行專案,會無法執行,同時可在下方看到出錯原因(如圖紅框處)。



Qt Quick Application 與 Qt Quick UI

我們在前一篇文章中所建立的專案是一個Qt Quick應用程式(Application),所謂的應用程式,表示該專案編譯的產出是應用程式,也就是一個執行檔,可以單獨運行,運行起來包括使用者介面,這個使用者介面是使用Qt Quick製作而成的。

在建立專案的過程中,選擇專案類型時,其中一個選項是"Qt Quick UI",選擇這個選項的話,該專案就只會有QML檔案,無法單獨運行。這類型的專案就是只有UI的部分,專案中只會有QML檔,沒有C++的原始碼,必須透過Qt內建的應用程式來開啟執行。


建立此類型專案,跟建立Qt Quick Application一樣,都要選擇Qt Quick元件組合。選單中可選擇的主要包括兩類,一類是Qt Quick Control 1.x,這個元件組合主要是UI控制物件,像是Button、Radio Box等等;另一類就是基本的Qt Quick (2.x 或 1.1)。


如果選擇Qt Quick 2.4,可以注意到下面的說明,Qt Quick 2.4有別於之前的模組,會有附檔名為".ui.qml"的檔案,這類型的檔案在Qt Creator中,預設會用Qt Quick Designer這款所見即所得的編輯工具來開啟。同時你可以注意到,這類型的專案,不需要透過編譯就可以用"QML Scene"這套內建工具來執行。


如果你選擇Qt Quick 1.1,與上面相同,都不需要經過編譯就可以透過內建工具來執行專案,差別在於Qt 1.x所採用的工具稱為"QML Viewer",關於"QML Scene"與"QML Viewer"的差異,在文章後半段會說明。


假設我們這邊先建立一個使用Qt Quick 2.4的Qt Quick UI專案,你可以看到,專案內的檔案,除了一個.qmlproject的檔案(角色與前篇文章所看到的.pro檔相同),還有一個主要的QML檔(HelloQtQuick.qml)以及一個自動產生的MainForm.ui.qml檔。



試著把滑鼠移到import後面的QtQuick 2.4上面,會跑出提示文字顯示該模組的所在路徑,在這個專案中,會自動產生一個主要的QML檔案(與專案名稱相同),內容很單純,就是一個MainForm的QML物件,裡面定義了一個函式。


點擊MainForm.ui.qml時,預設會以Qt Quick Designer來開啟,此工具為一所見即所得的編輯器,可以透過簡單的拖曳UI元件,並設定相關參數(如長寬、位置等),用法跟一般專用開發工具(如Visual Studio和Android Studio)很像,不過我們這邊不特別介紹此工具,而是以介紹QML編寫為主。


切換到編輯模式看一下MainForm.ui.qml看一下原始碼的部分,它是由一個Rectangle組成,裡面有一個MouseArea跟一個Text區塊,其實和上篇文章的畫面是一樣的。剛才我們看到主要的QML檔(HelloQtQuick.qml)裡只有一個名為MainForm的QML物件,這個MainForm是自定義的QML物件,也就是MainForm.ui.qml所定義的。其實這個檔案的檔名可以改為MainForm.qml,之所以檔名為xxx.ui.qml的目的是給Qt Creator判別使用Qt Quick Designer來開啟。

你可以注意到,在這邊的MouseArea中並沒有定義任何滑鼠事件,但實際上專案運行時還是能在單擊(onClicked)時離開程式,這邊使用了別名(alias)來達成這個目的,onClicked事件的定義則寫在HelloQtQuick.qml裡,關於別名(alias)的使用方式,後續會有相關篇幅說明。



Qt Quick 1 與 Qt Quick 2

在Qt 4.x時期官方所提供的Qt Quick框架為Qt Quick 1,所有的QML物件都集成在Qt Quick之中,到了Qt 5之後,Qt Quick框架則為Qt Quick 2,在Qt Quick 2中,將QML物件依照其物件類型和功能特性區分成幾個子模組,除此之外還提供了其他QML模組(QtWebKit)方便開發所使用,可參考此連結。Qt Quick 1與Qt Quick 2的差異在於底層繪製引擎(Render Engine)有所不同,然而在QML語法上是不變的,也當然是向下相容的。


QML Viewer 與 QML Scene

文章開頭的範例,是開啟了一個Qt Quick UI的專案,使用Qt Quick 2.4模組,從專案的執行設定可以看到,會使用"QML Scene"執行(如下圖紅框處)。前面也有提到,此類專案無法單獨運興,就是要靠QML Scene來解析QML檔案。


試著執行一下方才建立的專案,可以看到視窗標題有"qmlscene"的字樣


QML Scene可以視為QML的瀏覽器,就像是Web Browser與HTML文件的關係一樣,透過QML Scene載入QML文件,就可以依照QML內的定義來呈現結果。
QML Scene可解析使用Qt Quick 2.x相關模組的QML文件,相對於Qt Quick 2之於QML Scene,Qt Quick 1則是使用QML Viewer來解析;意即,使用了Qt Quick 1.x模組的QML文件,是無法用QML Scene來載入的,必須過QML Viewer來呈現其結果。

我們可以試著新建一個Qt Quick UI專案,選擇使用Qt Quick 1.1模組


自動產生的程式碼跟前面選擇Qt Quick 2的是一樣的,差別在引用的模組版本為QtQuick 1.1


專案開啟後,可以在執行設定看到,會使用"QML Viewer"執行(如下圖紅框處,因為中文版所以顯示QML檢視器)


透過Qt Creator來執行此類型的專案,就跟直接開啟QML Scene或QML Viewer來載入QML文件的結果是一樣的。QML Scene或QML Viewer這兩個內建應用程式,在Qt安裝時就會一併安裝至指定目錄,目錄在Qt的安裝目錄下(下圖示我的安裝目錄,一開始裝了Qt 5.3跟Qt 5.4,相對在mingw4.9跟mingw4.8的bin資料夾下都會有)


試著使用QML Scene來載入剛才建立的專案中的QML文件(HelloQtQuick.qml),我們可看到跟直接在Qt Creator上執行該專案的結果相同。



現在回到Qt Creator,我們先刻意把MainForm.ui.qml檔中 import 的模組改為 QtQuick 1.0,這時候Qt Creator會偵測到錯誤,因為在建立專案的時候是選擇Qt Quick 2.x,卻在QML文件中 import了Qt Quick 1.x,這種情況下會無法執行該專案,這是Qt Creator自動偵測的必然結果。


這時候,我們一樣用QML Scene來再開啟一次 HelloQtQuick.qml,就會發現無法正常呈現。

接著,我們開啟QML Viewer來載入我們剛才修改的QML檔(MainForm.ui.qml),是可以正常呈現的。






反之,你也可以試著將剛才修改的 import 模組改回 Qt Quick 2.3,然後再用QML Viewer去載入該文件,看看有甚麼樣的結果。

從以上說明,我們可以大概了解Qt Quick Application跟Qt Quick UI的不同,前一篇文章我們建立的是Qt Quick Application專案,與此篇文章所建立的Qt Quick UI專案執行結果相同,差別在Qt Quick Application有C++原始碼的部分,且可編譯成執行檔;而Qt Quick UI專案須透過QML Scene或QML Viewer執行。
我們可以視為Qt Quick Application中存在一個功能與QML Scene/QML Viewer類似的解析器,透過編譯將此解析器與QML文件包裹起來,變成一個可獨立運行的執行檔,這個解析器就是C++程式碼的部分,我們之後再針對此部分另闢一篇文章說明。




沒有留言:

張貼留言