#(83):Qt Quick Controls
自 QML 第一次發布已經過去一年多的時間,但在企業應用領域,QML 一直沒有能夠占據一定地位。很大一部分原因是,QML 缺少一些在企業應用中亟需的組件,比如按鈕、菜單等。雖然移動領域,這些組件已經變得可有可無,但在桌面系統中依然不可或缺。為了解決這一問題,Qt 5.1 發布了 Qt Quick 的一個全新模塊:Qt Quick Controls。顧名思義,這個模塊提供了大量類似 Qt Widgets 模塊那樣可重用的組件。本章我們將介紹 Qt Quick Controls,你會發現這個模塊與 Qt 組件非常類似。
為了開發基于 Qt Quick Controls 的程序,我們需要創建一個 Qt Quick Application 類型的應用程序,選擇組件集的時候注意選擇 Qt Quick Controls 即可:
[](http://files.devbean.net/images/2014/05/qqc-project-type.png)
注意,Qt Creator 給出的是 Qt Quick Controls 1.0,而最新版本的 Qt 5.2 搭載的 Qt Quick Controls 是 1.1。1.1 比 1.0 新增加了一些組件,比如`BusyIndicator`等。所以,如果你發現某個組件找不到,記得更新下 Qt Quick Controls 的版本。
Qt Quick Controls 1.1 提供了多種組件:
| 應用程序窗口 ||--|
| -- || -- |
| 用于描述應用程序的基本窗口屬性的組件 |
| ApplicationWindow | 對應`QMainWindow`,提供頂層應用程序窗口 |
| MenuBar | 對應`QMenuBar`,提供窗口頂部橫向的菜單欄 |
| StatusBar | 對應`QStatusBar`,提供狀態欄 |
| ToolBar | 對應`QToolBar`,提供工具欄,可以添加`ToolButton`和其它組件 |
| Action | 對應`QAction`,提供能夠綁定到導航和視圖的抽象的用戶界面動作 |
| 導航和視圖 |
| 方便用戶在一個布局中管理和顯示其它組件 |
| ScrollView | 對應`QScrollView`,提供滾動視圖 |
| SplitView | 對應`QSplitter`,提供可拖動的分割視圖布局 |
| StackView | 對應`QStackedWidget`,提供基于棧的層疊布局 |
| TabView | 對應`QTabWidget`,提供帶有標簽的基于棧的層疊布局 |
| TableView | 對應`QTableWidget`,提供帶有滾動條、樣式和表頭的表格 |
| 控件 |
| 控件用于表現或接受用戶輸入 |
| BusyIndicator | 提供忙等示意組件 |
| Button | 對應`QPushButton`,提供按鈕組件 |
| CheckBox | 對應`QCheckBox`,提供復選框 |
| ComboBox | 對應`QComboBox`,提供下拉框 |
| GroupBox | 對應`QGroupBox`,提供帶有標題、邊框的容器 |
| Label | 對應`QLabel`,提供標簽組件 |
| ProgressBar | 對應`QProgressBar`,提供進度條組件 |
| RadioButton | 對應`QRadioButton`,提供單選按鈕 |
| Slider | 對應`QSlider`,提供滑動組件 |
| SpinBox | 對應`QSpinBox`,提供微調組件 |
| Switch | 提供類似單選按鈕的開關組件 |
| TextArea | 對應`QTextEdit`,提供能夠顯示多行文本的富文本編輯框 |
| TextField | 對應`QTextLine`,提供顯示單行文本的純文本編輯框 |
| ToolButton | 對應`QToolButton`,提供在工具欄上顯示的工具按鈕 |
| ExclusiveGroup | 提供互斥 |
| 菜單 |
| 用于構建菜單的組件 |
| Menu | 對應`QMenu`,提供菜單、子菜單、彈出菜單等 |
| MenuSeparator | 提供菜單分隔符 |
| MenuItem | 提供添加到菜單欄或菜單的菜單項 |
| StatusBar | 對應`QStatusBar`,提供狀態欄 |
| ToolBar | 對應`QToolBar`,提供工具欄,可以添加`ToolButton`和其它組件 |
我們嘗試實現一個編輯器。這是一個簡單的文本編輯器,具有新建、剪切、復制和粘貼等操作。程序運行出來效果如下:
[](http://files.devbean.net/images/2014/05/simpleeditor.png)
整個程序都是在 IDE 幫我們生成的 main.qml 中實現的。首先我們需要添加`import`語句:
~~~
import QtQuick 2.1
import QtQuick.Controls 1.1
~~~
注意我們修改了 IDE 生成的默認語句。整個 QML 文檔的根元素是`ApplicationWindow`:
~~~
ApplicationWindow {
title: qsTr("Simple Editor")
width: 640
height: 480
...
}
~~~
`ApplicationWindow`是應用程序的主窗口,類似`QMainWindow`,提供了很多預定義的功能,比如菜單、工具欄等。代碼里面的`qsTr()`函數類似`tr()`函數,用于以后的國際化。所有面向用戶的文本都應該使用這個函數。
下面向`ApplicationWindow`中添加控件:
~~~
menuBar: MenuBar {
Menu {
title: qsTr("&File")
MenuItem { action: newAction }
MenuItem { action: exitAction }
}
Menu {
title: qsTr("&Edit")
MenuItem { action: cutAction }
MenuItem { action: copyAction }
MenuItem { action: pasteAction }
MenuSeparator {}
MenuItem { action: selectAllAction }
}
}
toolBar: ToolBar {
Row {
anchors.fill: parent
ToolButton { action: newAction }
ToolButton { action: cutAction }
ToolButton { action: copyAction }
ToolButton { action: pasteAction }
}
}
TextArea {
id: textArea
anchors.fill: parent
}
~~~
首先看最后面的`TextArea`,這是整個窗口的主要控件,類似于`setCentralWidget()`函數調用。
`menuBar`和`toolBar`兩個屬性都是`ApplicationWindow`提供的屬性。
`menuBar`是`MenuBar`類型的,所以我們創建一個新的`MenuBar`控件。`MenuBar`具有層次結構,這是通過`Menu`的嵌套實現的。每一個菜單項都是用`MenuItem`實現的;菜單項之間的分隔符則使用`MenuSeparator`控件。這點與 QtWidgets 有所不同。
`toolBar`是`Item`類型的,不過通常都會使用`ToolBar`控件。`ToolBar`默認沒有提供布局,因此我們必須給它設置一個布局。這里我們直接添加了一個`Row`,作為橫向工具欄的布局。這個工具欄要橫向充滿父窗口,因此設置錨點為`anchors.fill: parent`。雖然我們設置的是充滿整個父窗口,但是工具欄的行為是,如果其中只有一個子元素(比如這里的`Row`),那么工具欄的高度將被設置為這個子元素的`implicitHeight`屬性。這對結合布局使用非常有用。事實上,這也是工具欄最常用的方法。工具欄中添加了四個按鈕,都是`ToolButton`類型。
每一個`MenuItem`和`ToolButton`都添加了一個`action`屬性。下面是這部分代碼:
~~~
Action {
id: exitAction
text: qsTr("E&xit")
onTriggered: Qt.quit()
}
Action {
id: newAction
text: qsTr("New")
iconSource: "images/new.png"
onTriggered: {
textArea.text = "";
}
}
Action {
id: cutAction
text: qsTr("Cut")
iconSource: "images/cut.png"
onTriggered: textArea.cut()
}
Action {
id: copyAction
text: qsTr("Copy")
iconSource: "images/copy.png"
onTriggered: textArea.copy()
}
Action {
id: pasteAction
text: qsTr("Paste")
iconSource: "images/paste.png"
onTriggered: textArea.paste()
}
Action {
id: selectAllAction
text: qsTr("Select All")
onTriggered: textArea.selectAll()
}
~~~
`Action`類似`QAction`。這里我們還是使用`qsTr()`函數設置其顯示的文本。
使用`iconSource`屬性可以指定圖標。注意這里的圖標只能是位于文件系統中的,不能加載資源文件中的圖標(當然,這并不是絕對的。如果我們將整個 QML 文檔放在資源文件中,那么就可以直接加載資源文件中的圖標。我們會在后面的章節詳細介紹這種技術。)。當我們直接類似“images/new.png”這種路徑時,注意 QML 是運行時解釋的,因此這個路徑是相對與 QML 文件的路徑。所以這里的圖標需要放在與 main.qml 文件同目錄下的 images 目錄中。
`onTriggered`屬性是一種信號處理函數,后面可以添加 JavaScript 語句。如果是多條語句,可以使用大括號,例如`newAction`的`onTriggered`。QML 組件可以發出信號。與 C++ 不同的是,QML 組件的信號并不需要特別的連接語句,而是使用”on信號名字”的形式。比如,`Action`有一個名為`triggered`的信號,則其信號處理函數即為`onTriggered`。事實上,這是最簡單的一種信號槽的實現。不過,這種實現的困難在于,同一個信號只能有一個固定名字的信號處理函數。不過,我們也可以使用 connect 連接語句。后面的章節中將詳細介紹這一點。
至此,我們的編輯器便實現了。由于全部使用了`TextArea`提供的功能,所以代碼很簡單。不過,復雜的程序都是這些簡單的元素堆積而成,所以,我們現在只是簡單介紹,具體的控件使用還要根據文檔仔細研究。
附件:[SimpleEditor.zip](http://files.devbean.net/code/SimpleEditor.zip)
- (1)序
- (2)Qt 簡介
- (3)Hello, world!
- (4)信號槽
- (5)自定義信號槽
- (6)Qt 模塊簡介
- (7)MainWindow 簡介
- (8)添加動作
- (9)資源文件
- (10)對象模型
- (11)布局管理器
- (12)菜單欄、工具欄和狀態欄
- (13)對話框簡介
- (14)對話框數據傳遞
- (15)標準對話框 QMessageBox
- (16)深入 Qt5 信號槽新語法
- (17)文件對話框
- (18)事件
- (19)事件的接受與忽略
- (21)事件過濾器
- (22)事件總結
- (23)自定義事件
- (24)Qt 繪制系統簡介
- (25)畫刷和畫筆
- (26)反走樣
- (27)漸變
- (28)坐標系統
- (29)繪制設備
- (30)Graphics View Framework
- (31)貪吃蛇游戲(1)
- (32)貪吃蛇游戲(2)
- (33)貪吃蛇游戲(3)
- (34)貪吃蛇游戲(4)
- (35)文件
- (36)二進制文件讀寫
- (37)文本文件讀寫
- (38)存儲容器
- (39)遍歷容器
- (40)隱式數據共享
- (41)model/view 架構
- (42)QListWidget、QTreeWidget 和 QTableWidget
- (43)QStringListModel
- (44)QFileSystemModel
- (45)模型
- (46)視圖和委托
- (47)視圖選擇
- (48)QSortFilterProxyModel
- (49)自定義只讀模型
- (50)自定義可編輯模型
- (51)布爾表達式樹模型
- (52)使用拖放
- (53)自定義拖放數據
- (54)剪貼板
- (55)數據庫操作
- (56)使用模型操作數據庫
- (57)可視化顯示數據庫數據
- (58)編輯數據庫外鍵
- (59)使用流處理 XML
- (60)使用 DOM 處理 XML
- (61)使用 SAX 處理 XML
- (62)保存 XML
- (63)使用 QJson 處理 JSON
- (64)使用 QJsonDocument 處理 JSON
- (65)訪問網絡(1)
- (66)訪問網絡(2)
- (67)訪問網絡(3)
- (68)訪問網絡(4)
- (69)進程
- (70)進程間通信
- (71)線程簡介
- (72)線程和事件循環
- (73)Qt 線程相關類
- (74)線程和 QObject
- (75)線程總結
- (76)QML 和 QtQuick 2
- (77)QML 語法
- (78)QML 基本元素
- (79)QML 組件
- (80)定位器
- (81)元素布局
- (82)輸入元素
- (83)Qt Quick Controls
- (84)Repeater
- (85)動態視圖
- (86)視圖代理
- (87)模型-視圖高級技術
- (88)Canvas
- (89)Canvas(續)