1. 程式人生 > >Qt 學習之路 2(42):QListWidget、QTreeWidget 和 QTableWidget

Qt 學習之路 2(42):QListWidget、QTreeWidget 和 QTableWidget

上一章我們瞭解了 model/view 架構的基本概念。現在我們從最簡單的QListWidgetQTreeWidgetQTableWidget三個類開始瞭解最簡單的 model/view 的使用。這部分內容的確很難組織。首先,從最標準的 model/view 開始,往往會糾結於複雜的程式碼;但是,如果從簡單的 QListWidgetQTreeWidgetQTableWidget開始,由於這三個類都是繼承自各自的 view 類,很難避免 model/view 的相關內容。於是,我們這部分的組織是,首先進行簡單的資料顯示,更復雜的設定則放在後面的章節。

 

QListWidget

我們要介紹的第一個是QListWidget。先來看下面的程式碼示例:

C/C++

28 lines

 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

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是簡單的列表元件。當我們不需要複雜的列表時,可以選擇QListWidgetQListWidget中可以新增QListWidgetItem型別作為列表項,QListWidgetItem即可以有文字,也可以有圖示。上面的程式碼顯示了三種向列表中新增列表項的方法(實際是兩種,後兩種其實是一樣的),我們的列表元件是listWidget,那麼,向listWidget新增列表項可以:第一,使用下面的語句

C/C++

1 lines

 

1

new QListWidgetItem(QIcon(":/Chrome.png"), tr("Chrome"), listWidget);

第二,使用

C/C++

6 lines

 

1

2

3

4

5

6

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區別處理不同子類。

我們的程式的執行結果如下:

QListWidget 示例

我們可以利用QListWidget發出的各種訊號來判斷是哪個列表項被選擇,具體細節可以參考文件。另外,我們也可以改變列表的顯示方式。前面的列表是小圖示顯示,我們也可以更改為圖示顯示,只要新增一行語句:

C/C++

1 lines

 

1

listWidget->setViewMode(QListView::IconMode);

結果如下:

QListWidget IconMode 示例

QTreeWidget

我們要介紹的第二個元件是QTreeWidget。顧名思義,這是用來展示樹型結構(也就是層次結構)的。同前面說的QListWidget類似,這個類需要同另外一個輔助類QTreeWidgetItem一起使用。不過,既然是提供方面的封裝類,即便是看上去很複雜的樹,在使用這個類的時候也是顯得比較簡單的。當不需要使用複雜的QTreeView特性的時候,我們可以直接使用QTreeWidget代替。

下面我們使用程式碼構造一棵樹:

C/C++

14 lines

 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

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新增QTreeWidgetItemQTreeWidgetItem有很多過載的建構函式。我們在這裡看看其中的一個,其餘的請自行查閱文件。這個建構函式的簽名如下:

C/C++

1 lines

 

1

QTreeWidgetItem(QTreeWidget *parent, const QStringList &strings, int type = Type);

這裡有 3 個引數,第一個引數用於指定這個項屬於哪一個樹,類似前面的QListWidgetItem,如果指定了這個值,則意味著該項被直接新增到樹中;第二個引數指定顯示的文字;第三個引數指定其型別,同QListWidgetItemtype引數十分類似。值得注意的是,第二個引數是QStringList型別的,而不是QString型別。我們會在下文了解其含義。

在這段程式碼中,我們建立了作為根的QTreeWidgetItemroot。然後添加了第一個葉節點,之後又新增一個,而這個則設定了可選標記。最後,我們將這個 root 新增到一個QTreeWidgetItem的列表,作為QTreeWidget的資料項。此時你應該想到,既然QTreeWidget接受QList作為項的資料,它就能夠支援多棵樹的一起顯示,而不僅僅是單根樹。下面我們來看看執行結果:

QTreeWidget 示例

從程式碼來看,我們能夠想象到這個樣子,只是這個樹的頭上怎麼會有一個 1?還記得我們跳過去的那個函式嗎?下面我們修改一下程式碼看看:

C/C++

20 lines

 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

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 資源管理器的介面。

QTreeWidget 多欄示例

如果你不需要顯示這個表頭,可以呼叫setHeaderHidden()函式將其隱藏。

QTableWidget

我們要介紹的最後一個是 QTableWidgetQTableWidget並不比前面的兩個複雜到哪裡去,這點我們可以從程式碼看出來:

C/C++

16 lines

 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

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();

這段程式碼執行起來是這樣子的:

QTableWidget 示例

首先我們建立了QTableWidget物件,然後設定列數和行數。接下來使用一個QStringList,設定每一列的標題。我們可以通過呼叫setItem()函式來設定表格的單元格的資料。這個函式前兩個引數分別是行索引和列索引,這兩個值都是從 0 開始的,第三個引數則是一個QTableWidgetItem物件。Qt 會將這個物件放在第 row 行第 col 列的單元格中。有關QTableWidgetItem的介紹完全可以參見上面的QListWidgetItemQTreeWidgetItem

上一章我們瞭解了 model/view 架構的基本概念。現在我們從最簡單的QListWidgetQTreeWidgetQTableWidget三個類開始瞭解最簡單的 model/view 的使用。這部分內容的確很難組織。首先,從最標準的 model/view 開始,往往會糾結於複雜的程式碼;但是,如果從簡單的 QListWidgetQTreeWidgetQTableWidget開始,由於這三個類都是繼承自各自的 view 類,很難避免 model/view 的相關內容。於是,我們這部分的組織是,首先進行簡單的資料顯示,更復雜的設定則放在後面的章節。

 

QListWidget

我們要介紹的第一個是QListWidget。先來看下面的程式碼示例:

C/C++

28 lines

 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

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是簡單的列表元件。當我們不需要複雜的列表時,可以選擇QListWidgetQListWidget中可以新增QListWidgetItem型別作為列表項,QListWidgetItem即可以有文字,也可以有圖示。上面的程式碼顯示了三種向列表中新增列表項的方法(實際是兩種,後兩種其實是一樣的),我們的列表元件是listWidget,那麼,向listWidget新增列表項可以:第一,使用下面的語句

C/C++

1 lines

 

1

new QListWidgetItem(QIcon(":/Chrome.png"), tr("Chrome"), listWidget);

第二,使用

C/C++

6 lines

 

1

2

3

4

5

6

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區別處理不同子類。

我們的程式的執行結果如下:

QListWidget 示例

我們可以利用QListWidget發出的各種訊號來判斷是哪個列表項被選擇,具體細節可以參考文件。另外,我們也可以改變列表的顯示方式。前面的列表是小圖示顯示,我們也可以更改為圖示顯示,只要新增一行語句:

C/C++

1 lines

 

1

listWidget->setViewMode(QListView::IconMode);

結果如下:

QListWidget IconMode 示例

QTreeWidget

我們要介紹的第二個元件是QTreeWidget。顧名思義,這是用來展示樹型結構(也就是層次結構)的。同前面說的QListWidget類似,這個類需要同另外一個輔助類QTreeWidgetItem一起使用。不過,既然是提供方面的封裝類,即便是看上去很複雜的樹,在使用這個類的時候也是顯得比較簡單的。當不需要使用複雜的QTreeView特性的時候,我們可以直接使用QTreeWidget代替。

下面我們使用程式碼構造一棵樹:

C/C++

14 lines

 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

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新增QTreeWidgetItemQTreeWidgetItem有很多過載的建構函式。我們在這裡看看其中的一個,其餘的請自行查閱文件。這個建構函式的簽名如下:

C/C++

1 lines

 

1

QTreeWidgetItem(QTreeWidget *parent, const QStringList &strings, int type = Type);

這裡有 3 個引數,第一個引數用於指定這個項屬於哪一個樹,類似前面的QListWidgetItem,如果指定了這個值,則意味著該項被直接新增到樹中;第二個引數指定顯示的文字;第三個引數指定其型別,同QListWidgetItemtype引數十分類似。值得注意的是,第二個引數是QStringList型別的,而不是QString型別。我們會在下文了解其含義。

在這段程式碼中,我們建立了作為根的QTreeWidgetItemroot。然後添加了第一個葉節點,之後又新增一個,而這個則設定了可選標記。最後,我們將這個 root 新增到一個QTreeWidgetItem的列表,作為QTreeWidget的資料項。此時你應該想到,既然QTreeWidget接受QList作為項的資料,它就能夠支援多棵樹的一起顯示,而不僅僅是單根樹。下面我們來看看執行結果:

QTreeWidget 示例

從程式碼來看,我們能夠想象到這個樣子,只是這個樹的頭上怎麼會有一個 1?還記得我們跳過去的那個函式嗎?下面我們修改一下程式碼看看:

C/C++

20 lines

 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

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 資源管理器的介面。

QTreeWidget 多欄示例

如果你不需要顯示這個表頭,可以呼叫setHeaderHidden()函式將其隱藏。

QTableWidget

我們要介紹的最後一個是 QTableWidgetQTableWidget並不比前面的兩個複雜到哪裡去,這點我們可以從程式碼看出來:

C/C++

16 lines

 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

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();

這段程式碼執行起來是這樣子的:

QTableWidget 示例

首先我們建立了QTableWidget物件,然後設定列數和行數。接下來使用一個QStringList,設定每一列的標題。我們可以通過呼叫setItem()函式來設定表格的單元格的資料。這個函式前兩個引數分別是行索引和列索引,這兩個值都是從 0 開始的,第三個引數則是一個QTableWidgetItem物件。Qt 會將這個物件放在第 row 行第 col 列的單元格中。有關QTableWidgetItem的介紹完全可以參見上面的QListWidgetItemQTreeWidgetItem

https://www.devbean.net/2013/02/qt-study-road-2-qlistwidget-qtreewidget-qtablewidget/