上一章我们了解了 model/view 架构的基本概念。现在我们从最简单的QListWidget
、QTreeWidget
和QTableWidget
三个类开始了解最简单的 model/view 的使用。这部分内容的确很难组织。首先,从最标准的 model/view 开始,往往会纠结于复杂的代码;但是,如果从简单的 QListWidget
、QTreeWidget
和QTableWidget
开始,由于这三个类都是继承自各自的 view 类,很难避免 model/view 的相关内容。于是,我们这部分的组织是,首先进行简单的数据显示,更复杂的设置则放在后面的章节。
QListWidget
我们要介绍的第一个是QListWidget
。先来看下面的代码示例:
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
是简单的列表组件。当我们不需要复杂的列表时,可以选择QListWidget
。QListWidget
中可以添加QListWidgetItem
类型作为列表项,QListWidgetItem
即可以有文本,也可以有图标。上面的代码显示了三种向列表中添加列表项的方法(实际是两种,后两种其实是一样的),我们的列表组件是listWidget
,那么,向listWidget
添加列表项可以:第一,使用下面的语句
1
|
new
QListWidgetItem
(
QIcon
(
":/Chrome.png"
)
,
tr
(
"Chrome"
)
,
listWidget
)
;
|
第二,使用
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
发出的各种信号来判断是哪个列表项被选择,具体细节可以参考文档。另外,我们也可以改变列表的显示方式。前面的列表是小图标显示,我们也可以更改为图标显示,只要添加一行语句:
1
|
listWidget
->
setViewMode
(
QListView
::
IconMode
)
;
|
结果如下:
QTreeWidget
我们要介绍的第二个组件是QTreeWidget
。顾名思义,这是用来展示树型结构(也就是层次结构)的。同前面说的QListWidget
类似,这个类需要同另外一个辅助类QTreeWidgetItem
一起使用。不过,既然是提供方面的封装类,即便是看上去很复杂的树,在使用这个类的时候也是显得比较简单的。当不需要使用复杂的QTreeView
特性的时候,我们可以直接使用QTreeWidget
代替。
下面我们使用代码构造一棵树:
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
添加QTreeWidgetItem
。QTreeWidgetItem
有很多重载的构造函数。我们在这里看看其中的一个,其余的请自行查阅文档。这个构造函数的签名如下:
1
|
QTreeWidgetItem
(
QTreeWidget *
parent
,
const
QStringList
&
strings
,
int
type
=
Type
)
;
|
这里有 3 个参数,第一个参数用于指定这个项属于哪一个树,类似前面的QListWidgetItem
,如果指定了这个值,则意味着该项被直接添加到树中;第二个参数指定显示的文字;第三个参数指定其类型,同QListWidgetItem
的type
参数十分类似。值得注意的是,第二个参数是QStringList
类型的,而不是QString
类型。我们会在下文了解其含义。
在这段代码中,我们创建了作为根的QTreeWidgetItem
root。然后添加了第一个叶节点,之后又添加一个,而这个则设置了可选标记。最后,我们将这个 root 添加到一个QTreeWidgetItem
的列表,作为QTreeWidget
的数据项。此时你应该想到,既然QTreeWidget
接受QList
作为项的数据,它就能够支持多棵树的一起显示,而不仅仅是单根树。下面我们来看看运行结果:
从代码来看,我们能够想象到这个样子,只是这个树的头上怎么会有一个 1?还记得我们跳过去的那个函数吗?下面我们修改一下代码看看:
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 资源管理器的界面。
如果你不需要显示这个表头,可以调用setHeaderHidden()
函数将其隐藏。
QTableWidget
我们要介绍的最后一个是 QTableWidget
。QTableWidget
并不比前面的两个复杂到哪里去,这点我们可以从代码看出来:
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
对象,然后设置列数和行数。接下来使用一个QStringList
,设置每一列的标题。我们可以通过调用setItem()
函数来设置表格的单元格的数据。这个函数前两个参数分别是行索引和列索引,这两个值都是从 0 开始的,第三个参数则是一个QTableWidgetItem
对象。Qt 会将这个对象放在第 row 行第 col 列的单元格中。有关QTableWidgetItem
的介绍完全可以参见上面的QListWidgetItem
和QTreeWidgetItem
。