Qt中提供的多元素控件有:
- QListWidget
- QListView
- QTableWidget
- QTableView
- QTreeWidget
- QTreeView
以QTableWidget和QTableView为例.
- QTableView是基于MVC设计的控件.QTableView⾃⾝不持有数据.使⽤QTableView的时候需要⽤⼾创建⼀个Model对象(⽐如 QStandardModel ),并且把Model和QTableView关联起来.后续修改Model中的数据就会影响QTableView的显⽰;修改QTableView的显⽰也会影响到Model中的数据(双向绑定).
- QTableWidget则是QTableView的⼦类,对Model进⾏了封装.不需要⽤⼾⼿动创建Model对象,直接就可以往QTableWidget中添加数据了.
xxView是更底层的实现
xxWidget是基于xxView封装而来的~~ 此处xxView是MVC结构的一种典型实现
MVC也是软件开发中,非常经典的软件结构的组织形式了. - M model数据
- V view 视图 (界面)
- C controller控制器数据和视图之间的业务流程
此处xxView只是负责实现了视图
不负责数据如何存储表示,更不负责数据和视图之间的交互
因此如果使用xxView就需要程序员自己实现model 和controller的部分.就比较麻烦
xxWidget基于xxView同时把model和controller都帮我们实现好了
拿过来就可以使用.人家提供了功能很方便的api,让我们直接就用
List Widget
使⽤ QListWidget 能够显⽰⼀个纵向的列表.形如:
核⼼属性
属性 | 说明 |
---|---|
currentRow | 当前被选中的是第⼏⾏ |
count | ⼀共有多少⾏ |
sortingEnabled | 是否允许排序 |
isWrapping | 是否允许换⾏ |
itemAlignment | 元素的对⻬⽅式 |
selectRectVisible | 被选中的元素矩形是否可⻅ |
spacing | 元素之间的间隔 |
核⼼⽅法 |
⽅法 | 说明 |
---|---|
addItem(const QString&label) addItem(QListWidgetItem * item) | 列表中添加元素. |
currentItem() | 返回QListWidgetItem* 表⽰当前选中的元素 |
setCurrentItem(QListWidgetItem* item) | 设置选中哪个元素 |
setCurrentRow(int row) | 设置选中第⼏⾏的元素 |
insertItem(const QString& label,int row) insertItem(QListWidgetItem * item, int row) | 在指定的位置插⼊元素 |
item(int row) | 返回QListWidgetItem* 表⽰第row⾏的元素 |
takeItem(int row) | 删除指定⾏的元素,返回QListWidgetItem* 表⽰是哪个元素被删 除了 |
核⼼信号 |
⽅法 | 说明 |
---|---|
currentItemChanged(QListWidgetItem* current, QListWidgetItem * old) | 选中不同元素时会触发.参数是当前选中的元素和之前选中的元素. |
currentRowChanged(int) | 选中不同元素时会触发.参数是当前选中元素的⾏数. |
itemClicked(QListWidgetItem* item) | 点击某个元素时触发 |
itemDoubleClicked(QListWidgetItem* item) | 双击某个元素时触发 |
itemEntered(QListWidgetItem* item) | ⿏标进⼊元素时触发 |
在上述介绍中,涉及到⼀个关键的类, QListWidgetItem . | |
这个类表⽰ QListWidget 中的⼀个元素. | |
核⼼⽅法如下,本质上就是⼀个"⽂本+图标"构成的 |
⽅法 | 说明 |
---|---|
setFont | 设置字体 |
setIcon | 设置图标 |
setHidden | 设置隐藏 |
setSizeHint | 设置尺⼨ |
setSelected | 设置是否选中 |
setText | 设置⽂本 |
setTextAlignment | 设置⽂本对⻬⽅式. |
代码⽰例:使⽤ListWidget
1)在界⾯上创建⼀个 ListView ,右键=>变形为=> ListWidget ,再创建⼀个lineEdit和两个按钮.
注意: ListWidget 是 ListView 的⼦类,功能⽐ ListView 更丰富.使⽤ListWidget 即可.
2)编写widget.cpp,在构造函数中添加初始元素
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
//添加元素
ui->listWidget->addItem("C++");
ui->listWidget->addItem("Java");
ui->listWidget->addItem("Python");
// ui->listWidget->addItem(new QListWidgetItem("C++"));
// ui->listWidget->addItem(new QListWidgetItem("Java"));
// ui->listWidget->addItem(new QListWidgetItem("Python"));
}
在QListWidgetItem中,可以设置字体属性,设置图标,设置文字大小,设置是否被选中
或者直接点击添加项目
3)编写按钮的slot函数
void Widget::on_pushButton_insert_clicked()
{
//获取输入框中的内容
const QString& text = ui->lineEdit->text();
//添加到QListWidget中
ui->listWidget->addItem(text);
}
void Widget::on_pushButton_delete_clicked()
{
//先获取到哪个元素被选中
int row = ui->listWidget->currentRow();
if (row < 0) {
return;
}
//按照行号来删除元素
ui->listWidget->takeItem(row);
}
4)编写listWidget的slot函数
- 此处需要判定 current 和 previous ⾮空.初始情况下是没有元素选中的,就导致这俩指针可能是NULL.
void Widget::on_listWidget_currentItemChanged(QListWidgetItem *current, QListWidgetItem *previous)
{
//通过这个槽函数来感知到变化
if (current != nullptr) {
qDebug() << "当前选中的元素: " << current->text();
}
if (previous != nullptr) {
qDebug() << "上次选中的元素: " << previous->text();
}
}
这⾥需要给widget.h前⾯加上 #include <QListWidgetItem>
Table Widget
使⽤ QTableWidget 表⽰⼀个表格控件.⼀个表格中包含若⼲⾏,每⼀⾏⼜包含若⼲列.
表格中的每个单元格,是⼀个 QTableWidgetItem 对象.
QTableWidget 核⼼⽅法
⽅法 | 说明 |
---|---|
item(int row, int column) | 根据⾏数列数获取指定的 QTableWidgetItem* |
setItem(int row, int column, QTableWidget*) | 根据⾏数列数设置表格中的元素 |
currentItem() | 返回被选中的元素QTableWidgetItem* |
currentRow() | 返回被选中元素是第⼏⾏ |
currentColumn() | 返回被选中元素是第⼏列 |
row(QTableWidgetItem* ) | 获取指定item是第⼏⾏ |
column(QTableWidgetItem* ) | 获取指定item是第⼏列 |
rowCount() | 获取⾏数 |
columnCount() | 获取列数 |
insertRow(int row) | 在第row⾏处插⼊新⾏ |
insertColumn(int column) | 在第column列插⼊新列 |
removeRow(int row) | 删除第row⾏ |
removeColumn(int column) | 删除第column列 |
setHorizontalHeaderItem(int column,QTableWidget*) | 设置指定列的表头 |
setVerticalHeaderItem(int row, QTableWidget*) | 设置指定⾏的表头 |
QTableWidgetItem 核⼼信号
信号 | 说明 |
---|---|
cellClicked(int row, int column) | 点击单元格时触发 |
cellDoubleClicked(int row, int column) | 双击单元格时触发 |
cellEntered(int row, int column) | ⿏标进⼊单元格时触发 |
currentCellChanged(int row,int column, int previousRow, int previousColumn) | 选中不同单元格时触发 |
QTableWidgetItem 核⼼⽅法
⽅法 | 说明 |
---|---|
row() | 获取当前是第⼏⾏ |
column() | 获取当前是第⼏列 |
setText(const QString&) | 设置⽂本 |
setTextAlignment(int) | 设置⽂本对⻬ |
setIcon(const QIcon&) | 设置图标 |
setSelected(bool) | 设置被选中 |
setSizeHints(const QSize&) | 设置尺⼨ |
setFont(const QFont&) | 设置字体 |
代码⽰例:使⽤ QTableWidget
1)在界⾯上创建 QTableWidget 和三个按钮,⼀个输⼊框
注意: QTableWidget 是 QTableView 的⼦类,功能⽐ QTableView 更丰富.使⽤QTableWidget 即可.
可以在图形化界面初始化
2)编写widget.cpp构造函数,构造表格中的初始数据
#include "widget.h"
#include "ui_widget.h"
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
//创建3行
ui->tableWidget->insertRow(0);
ui->tableWidget->insertRow(1);
ui->tableWidget->insertRow(2);
//创建3列
ui->tableWidget->insertColumn(0);
ui->tableWidget->insertColumn(1);
ui->tableWidget->insertColumn(2);
//给3列设定列名(水平方向表头)
ui->tableWidget->setHorizontalHeaderItem(0, new QTableWidgetItem("学号"));
ui->tableWidget->setHorizontalHeaderItem(1, new QTableWidgetItem("姓名"));
ui->tableWidget->setHorizontalHeaderItem(2, new QTableWidgetItem("年龄"));
//添加数据
ui->tableWidget->setItem(0, 0, new QTableWidgetItem("1001"));
ui->tableWidget->setItem(0, 1, new QTableWidgetItem("张三"));
ui->tableWidget->setItem(0, 2, new QTableWidgetItem("20"));
ui->tableWidget->setItem(1, 0, new QTableWidgetItem("1002"));
ui->tableWidget->setItem(1, 1, new QTableWidgetItem("李四"));
ui->tableWidget->setItem(1, 2, new QTableWidgetItem("19"));
ui->tableWidget->setItem(2, 0, new QTableWidgetItem("1003"));
ui->tableWidget->setItem(2, 1, new QTableWidgetItem("王五"));
ui->tableWidget->setItem(2, 2, new QTableWidgetItem("20"));
}
3)编写按钮的slot函数
void Widget::on_pushButton_insertrow_clicked()
{
//需要知道当前一共有多少行
int rowCount = ui->tableWidget->rowCount();
//在最后一行之后新增新行
//此处的参数是下标,表示新增之后的这一行是第几行
ui->tableWidget->insertRow(rowCount);
}
void Widget::on_pushButton_deleterow_clicked()
{
//获取到要删除的选中的行号
int curRow = ui->tableWidget->currentRow();
//删除这一行
ui->tableWidget->removeRow(curRow);
}
void Widget::on_pushButton_insertcol_clicked()
{
//需要知道当前一共有多少列
int colCount = ui->tableWidget->columnCount();
//在最后一行之后新增新行
//此处的参数是下标,表示新增之后的这一行是第几行
ui->tableWidget->insertColumn(colCount);
const QString& text = ui->lineEdit->text();
ui->tableWidget->setHorizontalHeaderItem(colCount, new QTableWidgetItem(text));
}
void Widget::on_pushButton_deletecol_clicked()
{
//获取到要删除的选中的行号
int curCol = ui->tableWidget->currentColumn();
//删除这一行
ui->tableWidget->removeColumn(curCol);
}
默认情况下,单元格中的内容直接就是可编辑的.
如果不想让⽤⼾编辑,可以设置
ui->tableWidget->setEditTriggers(QAbstractItemView::NoEditTriggers);
Tree Widget
使⽤ QTreeWidget 表⽰⼀个树形控件.⾥⾯的每个元素,都是⼀个 QTreeWidgetItem ,每个QTreeWidgetItem 可以包含多个⽂本和图标,每个⽂本/图标为⼀个列.
可以给 QTreeWidget 设置顶层节点(顶层节点可以有多个),然后再给顶层节点添加⼦节点,从⽽构成树形结构.
QTreeWidget 核⼼⽅法
⽅法 | 说明 |
---|---|
clear | 清空所有⼦节点 |
addTopLevelItem(QTreeWidgetItem* item) | 新增顶层节点 |
topLevelItem(int index) | 获取指定下标的顶层节点. |
topLevelItemCount() | 获取顶层节点个数 |
indexOfTopLevelItem(QTreeWidgetItem* item) | 查询指定节点是顶层节点中的下标 |
takeTopLevelItem(int index) | 删除指定的顶层节点.返回QTreeWidgetItem* 表⽰被删除的元素 |
currentItem() | 获取到当前选中的节点,返回QTreeWidgetItem* |
setCurrentItem(QTreeWidgetItem* item) | 选中指定节点 |
setExpanded(bool) | 展开/关闭节点 |
setHeaderLabel(const QString& text) | 设置TreeWidget的header名称. |
QTreeWidget 核⼼信号
信号 | 说明 |
---|---|
currentItemChanged(QTreeWidgetItem* current, QTreeWidgetItem * old) | 切换选中元素时触发 |
itemClicked(QTreeWidgetItem* item, int col) | 点击元素时触发 |
itemDoubleClicked(QTreeWidgetItem* item,int col) | 双击元素时触发 |
itemEntered(QTreeWidgetItem* item, int col) | ⿏标进⼊时触发 |
itemExpanded(QTreeWidgetItem* item) | 元素被展开时触发 |
itemCollapsend(QTreeWidgetItem* item) | 元素被折叠时触发 |
QTreeWidgetItem 核⼼属性
属性 | 说明 |
---|---|
text | 持有的⽂本 |
textAlignment | ⽂本对⻬⽅式 |
icon | 持有的图表 |
font | ⽂本字体 |
hidden | 是否隐藏 |
disabled | 是否禁⽤ |
expand | 是否展开 |
sizeHint | 尺⼨⼤⼩ |
selected | 是否选中 |
QTreeWidgetItem 核⼼⽅法
⽅法 | 说明 |
---|---|
addChild(QTreeWidgetItem* child) | 新增⼦节点 |
childCount() | ⼦节点的个数 |
child(int index) | 获取指定下标的⼦节点.返回QTreeWidgetItem* |
takeChild(int index) | 删除对应下标的⼦节点 |
removeChild(QTreeWidgetItem* child) | 删除对应的⼦节点 |
parent() | 获取该元素的⽗节点 |
代码⽰例:使⽤ QTreeWidget
1)在界⾯上创建⼀个 TreeView ,右键=>变形为=> TreeWidget ,再创建⼀个lineEdit和两个按钮.
注意: TreeWidget 是 TreeView 的⼦类,功能⽐ TreeView 更丰富.使⽤ TreeWidget即可.
在图形界面添加元素
2)编写代码,构造初始数据
#include "widget.h"
#include "ui_widget.h"
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
//设置根节点名字
ui->treeWidget->setHeaderLabel("动物");
//新增顶层节点
QTreeWidgetItem* item1 = new QTreeWidgetItem();
//每个节点都可以设置多个列
item1->setText(0, "猫");
//添加到顶层节点中
ui->treeWidget->addTopLevelItem(item1);
//新增顶层节点
QTreeWidgetItem* item2 = new QTreeWidgetItem();
//每个节点都可以设置多个列
item2->setText(0, "狗");
//添加到顶层节点中
ui->treeWidget->addTopLevelItem(item2);
//新增顶层节点
QTreeWidgetItem* item3 = new QTreeWidgetItem();
//每个节点都可以设置多个列
item3->setText(0, "鸟");
//添加到顶层节点中
ui->treeWidget->addTopLevelItem(item3);
QTreeWidgetItem* item4 = new QTreeWidgetItem();
item4->setText(0, "中华田园猫");
item1->addChild(item4);
QTreeWidgetItem* item5 = new QTreeWidgetItem();
item5->setText(0, "布偶猫");
item1->addChild(item5);
QTreeWidgetItem* item6 = new QTreeWidgetItem();
item6->setText(0, "暹罗猫");
item1->addChild(item6);
}
void Widget::on_pushButton_insertTopLevelItem_clicked()
{
//获取到输入框的内容
const QString& text = ui->lineEdit->text();
//构造QTreeWidgetItem
QTreeWidgetItem* item = new QTreeWidgetItem();
item->setText(0, text);
//添加到顶层节点
ui->treeWidget->addTopLevelItem(item);
}
void Widget::on_pushButton_insertItem_clicked()
{
//获取到当前选中的节点
QTreeWidgetItem* currentItem = ui->treeWidget->currentItem();
if (currentItem == nullptr) {
return;
}
//获取到输入框的内容
const QString& text = ui->lineEdit->text();
//构造QTreeWidgetItem
QTreeWidgetItem* item = new QTreeWidgetItem();
item->setText(0, text);
//插入到选中节点的子节点
currentItem->addChild(item);
}
void Widget::on_pushButton_deleteItem_clicked()
{
//获取到当前元素
QTreeWidgetItem* currentItem = ui->treeWidget->currentItem();
if (currentItem == nullptr) {
return;
}
//删除,先获取到父元素
QTreeWidgetItem* parent = currentItem->parent();
if (parent == nullptr) {
//顶层元素
int index = ui->treeWidget->indexOfTopLevelItem(currentItem);
ui->treeWidget->takeTopLevelItem(index);
} else {
//普通元素
parent->removeChild(currentItem);
}
}
上述这几个控件相关的操作,数据都是在内存中保存的.无论在界面上做任何操作,重新运行程序,之前的数据就都没了
如果要想让数据能够重启也不丢失,就需要编写更多的代码吧内存存储的数据获取到,写入到文件中,并且在下次运行的时候从文件加载数据