#(41):QListWidget、QTreeWidget 和 QTableWidget
上一章我們了解了 model/view 架構的基本概念。現在我們從最簡單的`QListWidget`、`QTreeWidget`和`QTableWidget`三個類開始了解最簡單的 model/view 的使用。這部分內容的確很難組織。首先,從最標準的 model/view 開始,往往會糾結于復雜的代碼;但是,如果從簡單的?`QListWidget`、`QTreeWidget`和`QTableWidget`開始,由于這三個類都是繼承自各自的 view 類,很難避免 model/view 的相關內容。于是,我們這部分的組織是,首先進行簡單的數據顯示,更復雜的設置則放在后面的章節。
## QListWidget
我們要介紹的第一個是`QListWidget`。先來看下面的代碼示例:
~~~
label = new QLabel(this);
label->setFixedWidth(70);
listWidget = new QListWidget(this);
new QListWidgetItem(QIcon(":/Chrome.png"), tr("Chrome"), listWidget);
new QListWidgetItem(QIcon(":/Firefox.png"), tr("Firefox"), listWidget);
listWidget->addItem(new QListWidgetItem(QIcon(":/IE.png"), tr("IE")));
listWidget->addItem(new QListWidgetItem(QIcon(":/Netscape.png"), tr("Netscape")));
listWidget->addItem(new QListWidgetItem(QIcon(":/Opera.png"), tr("Opera")));
listWidget->addItem(new QListWidgetItem(QIcon(":/Safari.png"), tr("Safari")));
listWidget->addItem(new QListWidgetItem(QIcon(":/TheWorld.png"), tr("TheWorld")));
listWidget->addItem(new QListWidgetItem(QIcon(":/Traveler.png"), tr("Traveler")));
QListWidgetItem *newItem = new QListWidgetItem;
newItem->setIcon(QIcon(":/Maxthon.png"));
newItem->setText(tr("Maxthon"));
listWidget->insertItem(3, newItem);
QHBoxLayout *layout = new QHBoxLayout;
layout->addWidget(label);
layout->addWidget(listWidget);
setLayout(layout);
connect(listWidget, SIGNAL(currentTextChanged(QString)),
label, SLOT(setText(QString)));``
~~~
`QListWidget`是簡單的列表組件。當我們不需要復雜的列表時,可以選擇`QListWidget`。`QListWidget`中可以添加`QListWidgetItem`類型作為列表項,`QListWidgetItem`即可以有文本,也可以有圖標。上面的代碼顯示了三種向列表中添加列表項的方法(實際是兩種,后兩種其實是一樣的),我們的列表組件是`listWidget`,那么,向`listWidget`添加列表項可以:第一,使用下面的語句
~~~
new QListWidgetItem(QIcon(":/Chrome.png"), tr("Chrome"), listWidget);
~~~
第二,使用
~~~
listWidget->addItem(new QListWidgetItem(QIcon(":/IE.png"), tr("IE")));
// 或者
QListWidgetItem *newItem = new QListWidgetItem;
newItem->setIcon(QIcon(":/Maxthon.png"));
newItem->setText(tr("Maxthon"));
listWidget->insertItem(3, newItem);
~~~
注意這兩種添加方式的區別:第一種需要在構造時設置所要添加到的`QListWidget`對象;第二種方法不需要這樣設置,而是要調用`addItem()`或者`insertItem()`自行添加。如果你仔細查閱`QListWidgetItem`的構造函數,會發現有一個默認的`type`參數。該參數有兩個合法值:`QListWidgetItem::Type`(默認)和`QListWidgetItem::UserType`。如果我們繼承`QListWidgetItem`,可以設置該參數,作為我們子類的一種區別,以便能夠在`QListWidget`區別處理不同子類。
我們的程序的運行結果如下:
[](http://files.devbean.net/images/2013/01/listwidget-demo.png)
我們可以利用`QListWidget`發出的各種信號來判斷是哪個列表項被選擇,具體細節可以參考文檔。另外,我們也可以改變列表的顯示方式。前面的列表是小圖標顯示,我們也可以更改為圖標顯示,只要添加一行語句:
~~~
listWidget->setViewMode(QListView::IconMode);
~~~
結果如下:
[](http://files.devbean.net/images/2013/01/listwidget-icon-mode-demo.png)
##QTreeWidget
我們要介紹的第二個組件是`QTreeWidget`。顧名思義,這是用來展示樹型結構(也就是層次結構)的。同前面說的`QListWidget`類似,這個類需要同另外一個輔助類`QTreeWidgetItem`一起使用。不過,既然是提供方面的封裝類,即便是看上去很復雜的樹,在使用這個類的時候也是顯得比較簡單的。當不需要使用復雜的`QTreeView`特性的時候,我們可以直接使用`QTreeWidget`代替。
下面我們使用代碼構造一棵樹:
~~~
QTreeWidget treeWidget;
treeWidget.setColumnCount(1);
QTreeWidgetItem *root = new QTreeWidgetItem(&treeWidget,
QStringList(QString("Root")));
new QTreeWidgetItem(root, QStringList(QString("Leaf 1")));
QTreeWidgetItem *leaf2 = new QTreeWidgetItem(root, QStringList(QString("Leaf 2")));
leaf2->setCheckState(0, Qt::Checked);
QList<QTreeWidgetItem *> rootList;
rootList << root;
treeWidget.insertTopLevelItems(0, rootList);
treeWidget.show();
~~~
首先,我們創建了一個`QTreeWidget`實例。然后我們調用`setColumnCount()`函數設定欄數。這個函數的效果我們會在下文了解到。最后,我們向`QTreeWidget`添加`QTreeWidgetItem`。`QTreeWidgetItem`有很多重載的構造函數。我們在這里看看其中的一個,其余的請自行查閱文檔。這個構造函數的簽名如下:
~~~
QTreeWidgetItem(QTreeWidget *parent, const QStringList &strings, int type = Type);
~~~
這里有 3 個參數,第一個參數用于指定這個項屬于哪一個樹,類似前面的`QListWidgetItem`,如果指定了這個值,則意味著該項被直接添加到樹中;第二個參數指定顯示的文字;第三個參數指定其類型,同`QListWidgetItem`的`type`參數十分類似。值得注意的是,第二個參數是`QStringList`類型的,而不是`QString`類型。我們會在下文了解其含義。
在這段代碼中,我們創建了作為根的`QTreeWidgetItem`root。然后添加了第一個葉節點,之后又添加一個,而這個則設置了可選標記。最后,我們將這個 root 添加到一個`QTreeWidgetItem`的列表,作為`QTreeWidget`的數據項。此時你應該想到,既然`QTreeWidget`接受`QList`作為項的數據,它就能夠支持多棵樹的一起顯示,而不僅僅是單根樹。下面我們來看看運行結果:
[](http://files.devbean.net/images/2013/01/treewidget-demo.png)
從代碼來看,我們能夠想象到這個樣子,只是這個樹的頭上怎么會有一個 1?還記得我們跳過去的那個函數嗎?下面我們修改一下代碼看看:
~~~
QTreeWidget treeWidget;
QStringList headers;
headers << "Name" << "Number";
treeWidget.setHeaderLabels(headers);
QStringList rootTextList;
rootTextList << "Root" << "0";
QTreeWidgetItem *root = new QTreeWidgetItem(&treeWidget, rootTextList);
new QTreeWidgetItem(root, QStringList() << QString("Leaf 1") << "1");
QTreeWidgetItem *leaf2 = new QTreeWidgetItem(root,
QStringList() << QString("Leaf 2") << "2");
leaf2->setCheckState(0, Qt::Checked);
QList<QTreeWidgetItem *> rootList;
rootList << root;
treeWidget.insertTopLevelItems(0, rootList);
treeWidget.show();
~~~
這次我們沒有使用`setColumnCount()`,而是直接使用`QStringList`設置了 headers,也就是樹的表頭。接下來我們使用的還是`QStringList`設置數據。這樣,我們實現的是帶有層次結構的樹狀表格。利用這一屬性,我們可以比較簡單地實現類似 Windows 資源管理器的界面。
[](http://files.devbean.net/images/2013/02/treewidget-demo-2.png)
如果你不需要顯示這個表頭,可以調用`setHeaderHidden()`函數將其隱藏。
### `QTableWidget`
我們要介紹的最后一個是?`QTableWidget`。`QTableWidget`并不比前面的兩個復雜到哪里去,這點我們可以從代碼看出來:
~~~
QTableWidget tableWidget;
tableWidget.setColumnCount(3);
tableWidget.setRowCount(5);
QStringList headers;
headers << "ID" << "Name" << "Age" << "Sex";
tableWidget.setHorizontalHeaderLabels(headers);
tableWidget.setItem(0, 0, new QTableWidgetItem(QString("0001")));
tableWidget.setItem(1, 0, new QTableWidgetItem(QString("0002")));
tableWidget.setItem(2, 0, new QTableWidgetItem(QString("0003")));
tableWidget.setItem(3, 0, new QTableWidgetItem(QString("0004")));
tableWidget.setItem(4, 0, new QTableWidgetItem(QString("0005")));
tableWidget.setItem(0, 1, new QTableWidgetItem(QString("20100112")));
tableWidget.show();
~~~
[](http://files.devbean.net/images/2013/02/tablewidget-demo.png)
首先我們創建了`QTableWidget`對象,然后設置列數和行數。接下來使用一個`QStringList`,設置每一列的標題。我們可以通過調用`setItem()`函數來設置表格的單元格的數據。這個函數前兩個參數分別是行索引和列索引,這兩個值都是從 0 開始的,第三個參數則是一個`QTableWidgetItem`對象。Qt 會將這個對象放在第 row 行第 col 列的單元格中。有關`QTableWidgetItem`的介紹完全可以參見上面的`QListWidgetItem`和`QTreeWidgetItem`。
- (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(續)