找回密码
 立即注册
收起左侧

Qt学习之路第42篇 QListWidget、QTreeWidget 和 QTableWidget

9
回复
23641
查看
[复制链接]
累计签到:3 天
连续签到:1 天
来源: 2013-9-9 16:14:42 显示全部楼层 |阅读模式
版权声明

该文章原创于Qter开源社区(www.qter.org),作者devbean,博客www.devbean.net,转载请注明出处!


上一章我们了解了 model/view 架构的基本概念。现在我们从最简单的 QListWidget、QTreeWidget 和 QTableWidget 三个类开始了解最简单的 model/view 的使用。这部分内容的确很难组织。首先,从最标准的 model/view 开始,往往会纠结于复杂的代码;但是,如果从简单的 QListWidget、QTreeWidget 和 QTableWidget 开始,由于这三个类都是继承自各自的 view 类,很难避免 model/view 的相关内容。于是,我们这部分的组织是,首先进行简单的数据显示,更复杂的设置则放在后面的章节。



QListWidget

我们要介绍的第一个是 QListWidget。先来看下面的代码示例:

  1. label = new QLabel(this);
  2. label->setFixedWidth(70);

  3. listWidget = new QListWidget(this);

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

  6. listWidget->addItem(new QListWidgetItem(QIcon(":/IE.png"), tr("IE")));
  7. listWidget->addItem(new QListWidgetItem(QIcon(":/Netscape.png"), tr("Netscape")));
  8. listWidget->addItem(new QListWidgetItem(QIcon(":/Opera.png"), tr("Opera")));
  9. listWidget->addItem(new QListWidgetItem(QIcon(":/Safari.png"), tr("Safari")));
  10. listWidget->addItem(new QListWidgetItem(QIcon(":/TheWorld.png"), tr("TheWorld")));
  11. listWidget->addItem(new QListWidgetItem(QIcon(":/Traveler.png"), tr("Traveler")));

  12. QListWidgetItem *newItem = new QListWidgetItem;
  13. newItem->setIcon(QIcon(":/Maxthon.png"));
  14. newItem->setText(tr("Maxthon"));
  15. listWidget->insertItem(3, newItem);

  16. QHBoxLayout *layout = new QHBoxLayout;
  17. layout->addWidget(label);
  18. layout->addWidget(listWidget);

  19. setLayout(layout);

  20. connect(listWidget, SIGNAL(currentTextChanged(QString)),
  21.         label, SLOT(setText(QString)));
复制代码

QListWidget 是简单的列表组件。当我们不需要复杂的列表时,可以选择 QListWidget。QListWidget 中可以添加 QListWidgetItem 类型作为列表项,QListWidgetItem 即可以有文本,也可以有图标。上面的代码显示了三种向列表中添加列表项的方法(实际是两种,后两种其实是一样的),我们的列表组件是 listWidget,那么,向 listWidget 添加列表项可以:第一,使用下面的语句

  1. new QListWidgetItem(QIcon(":/Chrome.png"), tr("Chrome"), listWidget);
复制代码

第二,使用

  1. listWidget->addItem(new QListWidgetItem(QIcon(":/IE.png"), tr("IE")));
  2. // 或者
  3. QListWidgetItem *newItem = new QListWidgetItem;
  4. newItem->setIcon(QIcon(":/Maxthon.png"));
  5. newItem->setText(tr("Maxthon"));
  6. 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. QTreeWidget treeWidget;
  2. treeWidget.setColumnCount(1);

  3. QTreeWidgetItem *root = new QTreeWidgetItem(&treeWidget,
  4.                                             QStringList(QString("Root")));
  5. new QTreeWidgetItem(root, QStringList(QString("Leaf 1")));
  6. QTreeWidgetItem *leaf2 = new QTreeWidgetItem(root, QStringList(QString("Leaf 2")));
  7. leaf2->setCheckState(0, Qt::Checked);

  8. QList<QTreeWidgetItem *> rootList;
  9. rootList << root;
  10. treeWidget.insertTopLevelItems(0, rootList);

  11. 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. QTreeWidget treeWidget;

  2. QStringList headers;
  3. headers << "Name" << "Number";
  4. treeWidget.setHeaderLabels(headers);

  5. QStringList rootTextList;
  6. rootTextList << "Root" << "0";
  7. QTreeWidgetItem *root = new QTreeWidgetItem(&treeWidget, rootTextList);

  8. new QTreeWidgetItem(root, QStringList() << QString("Leaf 1") << "1");
  9. QTreeWidgetItem *leaf2 = new QTreeWidgetItem(root,
  10.                                    QStringList() << QString("Leaf 2") << "2");
  11. leaf2->setCheckState(0, Qt::Checked);

  12. QList<QTreeWidgetItem *> rootList;
  13. rootList << root;
  14. treeWidget.insertTopLevelItems(0, rootList);

  15. treeWidget.show();
复制代码

这次我们没有使用 setColumnCount(),而是直接使用 QStringList 设置了 headers,也就是树的表头。接下来我们使用的还是 QStringList 设置数据。这样,我们实现的是带有层次结构的树状表格。利用这一属性,我们可以比较简单地实现类似 Windows 资源管理器的界面。




如果你不需要显示这个表头,可以调用 setHeaderHidden() 函数将其隐藏。



QTableWidget

我们要介绍的最后一个是 QTableWidget。QTableWidget 并不比前面的两个复杂到哪里去,这点我们可以从代码看出来:

  1. QTableWidget tableWidget;
  2. tableWidget.setColumnCount(3);
  3. tableWidget.setRowCount(5);

  4. QStringList headers;
  5. headers << "ID" << "Name" << "Age" << "**";
  6. tableWidget.setHorizontalHeaderLabels(headers);

  7. tableWidget.setItem(0, 0, new QTableWidgetItem(QString("0001")));
  8. tableWidget.setItem(1, 0, new QTableWidgetItem(QString("0002")));
  9. tableWidget.setItem(2, 0, new QTableWidgetItem(QString("0003")));
  10. tableWidget.setItem(3, 0, new QTableWidgetItem(QString("0004")));
  11. tableWidget.setItem(4, 0, new QTableWidgetItem(QString("0005")));
  12. tableWidget.setItem(0, 1, new QTableWidgetItem(QString("20100112")));

  13. tableWidget.show();
复制代码

这段代码运行起来是这样子的:





首先我们创建了 QTableWidget 对象,然后设置列数和行数。接下来使用一个 QStringList,设置每一列的标题。我们可以通过调用 setItem() 函数来设置表格的单元格的数据。这个函数前两个参数分别是行索引和列索引,这两个值都是从 0 开始的,第三个参数则是一个 QTableWidgetItem 对象。Qt 会将这个对象放在第 row 行第 col 列的单元格中。有关 QTableWidgetItem 的介绍完全可以参见上面的 QListWidgetItem 和 QTreeWidgetItem。





本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
回复

使用道具 举报

累计签到:1 天
连续签到:1 天
2018-11-7 00:16:56 显示全部楼层
关于QTreeWidget的那段:
QList<QTreeWidgetItem *> rootList;
rootList << root;
treeWidget.insertTopLevelItems(0, rootList);
这段我觉得重复添加了,因为之前new QTreeWidgetItem时已经通过参数指定了所属widget, 所以item已经被加入到控件里了,但是居然没出现双份?难道控件自己检查了是否重复插入?
回复 支持 1 反对 0

使用道具 举报

累计签到:46 天
连续签到:1 天
2013-9-24 11:00:18 显示全部楼层
QTreeWidgetItem *root = new QTreeWidgetItem(&treeWidget,QStringList(QString("Root")));
如果将“Root”改成汉字,该怎么办?
回复 支持 反对

使用道具 举报

累计签到:3 天
连续签到:1 天
2013-10-2 15:53:56 显示全部楼层
kang清峻 发表于 2013-9-24 11:00
QTreeWidgetItem *root = new QTreeWidgetItem(&treeWidget,QStringList(QString("Root")));
如果将“Root ...

尽量不要在源代码中出现汉字,否则很容易出现编码问题。如果需要汉字,建议使用 tr() 函数,然后再使用国际化翻译文本。如果一定要在源代码中使用汉字,Qt5 需要注意文件需要保存为 UTF-8 格式;Qt4 的话需要在启动时设置 QTextCodec 等,可以看看这方面的文档
回复 支持 反对

使用道具 举报

累计签到:2 天
连续签到:1 天
2013-11-21 10:48:02 显示全部楼层
QListWidget  如果要删除某一选项呢
回复 支持 反对

使用道具 举报

累计签到:17 天
连续签到:1 天
2014-8-27 15:39:58 显示全部楼层
水平和垂直混合布局 怎么用?
回复 支持 反对

使用道具 举报

累计签到:1 天
连续签到:1 天
2016-3-22 14:28:25 显示全部楼层
看看呢~~~~~               
回复 支持 反对

使用道具 举报

累计签到:61 天
连续签到:2 天
2017-5-30 21:40:33 显示全部楼层
楼主写的不错,赞一个
回复 支持 反对

使用道具 举报

累计签到:5 天
连续签到:1 天
2017-6-2 12:23:29 显示全部楼层
有没有系列的学习文档呀
回复 支持 反对

使用道具 举报

尚未签到

2019-4-4 16:20:58 显示全部楼层
QTreeWidget和QTableWidget运行的界面是空的,是什么原因?
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

公告
可以关注我们的微信公众号yafeilinux_friends获取最新动态,或者加入QQ会员群进行交流:190741849、186601429(已满) 我知道了