Qt 常用控件 - 9

输入类控件我们基本了解之后,我们接下来来学习多元素控件!

多元素控件

Qt 中提供的多元素控件有:

列表

  • QListWidget

  • QListView

表格

  • QTableWidget

  • QTableView

树形:比如目录

  • QTreeWidget

  • QTreeView

💡 xxWidget 和 xxView 之间的区别 以 QTableWidget 和 QTableView 为例。

  • QTableView 是基于 MVC(MVC --- model:数据,view:视图,controller:控制器 --- 也是软件开发中,非常经典的软件结构的组织形式了) 设计的控件. QTableView 自身不持有数据. 使用 QTableView 的时候需要用户创建一个 Model 对象 (比如 qStandardItem ), 并且把 Model 和 QTableView 关联起来. 后续修改 Model 中的数据就会影响 QTableView 的显示; 修改 QTableView 的显示也会影响到 Model 中的数据(双向绑定).

  • QTableWidget 则是 QTableView 的子类, 对 Model 进行了封装. 不需要用户手动创建 Model 对象, 直接就可以在 QTableWidget 中添加数据了.

  • xxView 是更底层的实现,xxWidget 是基于 xxView 封装而来的!

List Widget

使用 QListWidget 能够显示一个纵向的列表. 形如:

每个选项都可以被选中.

核心属性
属性 说明
currentRow 当前被选中的是第几行
count 一共有多少行
sortingEnabled 是否允许排序
isWrapping 是否允许换行
itemAlignment 元素的对齐方式
selectRectVisible 被选中的元素矩形是否可见
spacing 元素之间的间隔
核心方法
方法 说明
addItem(const QString& label) addItem(QListWidgetItem *item) 列表中添加元素
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) 在指定的位置插入元素
insertItem(const QString& label, int row) insertItem(QListWidgetItem *item, int row) 此处的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 中的一个元素!

核心方法如下:本质上就是一个"文本+图标"构成的:

QListWidgetItem 的核心方法
方法 说明
setFont 设置字体
setIcon 设置图标
setHidden 设置隐藏
setSizeHint 设置尺寸
setSelected 设置是否选中
setText 设置文本
setTextAlignment 设置文本对齐方式
代码示例: 使用 ListWidget

1.在界面上创建一个 ListView, 右键 -> 变形为 -> ListWidget, 再创建一个 lineEdit 和两个按钮.

注意: ListWidget 是 ListView 的子类, 功能比 ListView 更丰富, 咱们使用 ListWidget 即可.

2.编写 widget.cpp, 在构造函数中添加初始元素

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");
    
    // 在 QListWidgetItem 中,可以设置字体属性,设置属性,设置文字大小,设置是否被选中等状态!
    // ui->listWidget->addItem(new QListWidgetItem("C++"));
    // ui->listWidget->addItem(new QListWidgetItem("Java"));
    // ui->listWidget->addItem(new QListWidgetItem("Python"));
    
    
}

我们也可以在图形化界面中,右击 QListWidget 选择编辑项目,就可以直接添加内容了,如果这里的初始化内容是固定的,此时我们通过哪种方式都可以,但是这里的内容不是固定的,要通过读取文件/网络来构造数据!就需要通过代码的方式来添加了!

3.编写 listWidget 的 slot 函数

此处需要判定 current 和 previous 非空. 初始情况下是没有元素选中的, 就导致这俩指针可能是 NULL

cpp 复制代码
void Widget::on_listWidget_currentItemChanged(QListWidgetItem * current, QListWidgetItem * previous)
{
    if (current != NULL && previous != NULL) {
        qDebug() << "当前选中: " << current->text()
                << "之前选中: " << previous->text();
    }
}

这里需要给 widget.h 前面加上 #include <QListWidgetItem>

4.编写按钮的 slot 函数

cpp 复制代码
void Widget::on_pushButton_clicked()
{
    // 1.先获取到输入框中的内容。
    const QString& text = ui->lineEdit->text();
    // 2.添加到 QListWidget 中
    if(text == "")
    {
        return;
    }
    ui->listWidget->addItem(text);
}


void Widget::on_pushButton_2_clicked()
{
    // 1.获取到被选中的元素是哪一个
    int row = ui->listWidget->currentRow();
    if(row < 0)
    {
        return;
    }
    // 2.按照行号来删除元素
    ui->listWidget->takeItem(row);
}

5.执行程序, 观察效果. 可以新增元素, 选中元素, 删除元素.


Table Widget

使用 QTableWidget 表示一个表格控件. 一个表格中包含若干行, 每一行又包含若干列. 表格中的每个单元格, 是一个 QTableWidgetItem 对象.

QTableWidget 核心方法
方法 说明
item(int row, int column) 根据行数列数获取指定的 QTableWidgetItem*
setItem(int row, int column, QTableWidgetItem*) 根据行数列数设置表格中的元素
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, QTableWidgetItem*) 设置指定列的表头(描述内容信息)
setVerticalHeaderItem(int row, QTableWidgetItem*) 设置指定行的表头
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 构造函数, 构造表格中的初始数据.

cpp 复制代码
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    // 对表格中的数据进行初始化 --- 我们可以使用代码,也可以使用图形化界面的方式
    // 创建三行
    ui->tableWidget->insertRow(0);
    ui->tableWidget->insertRow(1);
    ui->tableWidget->insertRow(2);
    // 创建三列
    ui->tableWidget->insertColumn(0);
    ui->tableWidget->insertColumn(1);
    ui->tableWidget->insertColumn(2);
    // 给三个列设置列名,也就是设置水平方向的表头
    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 函数

cpp 复制代码
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(currRow);
}


void Widget::on_pushButton_insertColumn_clicked()
{
    // 先获取到一共有几行
    int columunCount = ui->tableWidget->columnCount();
    // 在对应的位置新增这一列
    ui->tableWidget->insertColumn(columunCount);
    // 设置列名 -- 重重输入框中获取到
    const QString& text = ui->lineEdit->text();
    ui->tableWidget->setHorizontalHeaderItem(columunCount,new QTableWidgetItem(text));
}


void Widget::on_pushButton_4_clicked()
{
    // 获取到选中的列
    int curCol = ui->tableWidget->currentColumn();
    //删除这一列
    ui->tableWidget->removeColumn(curCol);
}

4.执行程序, 即可完成表格的基本操作.

默认情况下, 单元格中的内容直接就是可编辑的. 如果不想让用户编辑, 可以设置:

ui->tablewidget->setEditTriggers(QAbstractItemView::NoEditTriggers);

Tree Widget

使用 QTreewWidget 表示一个树形控件. 里面的每个元素, 都是一个 QTreewWidgetItem ,每个QTreeWidgetItem 可以包含多个文本和图标, 每个文本/图标为一个 列.

可以给 QTreeWidget 设置顶层节点(顶层节点可以有多个), 然后再给顶层节点添加子节点, 从而构成树形结构.

QTreeWidget 控件虽然是树形结构,但是这个树形结构没有体现出根节点,是从根节点的下一层 --- 子节点,开始计算的!

对于顶层节点来说,就可以看成是"List"这样的结构!

我们可以看成是 QTableWidget 的进化版本!

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) 元素被展开时触发
itemCollapsed(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 NFA, 功能比 TreeView 更丰富. 咱们使用 Treewidget 即可!

2.编写代码, 构造初始数据(我们也可以通过图形化界面编辑)

cpp 复制代码
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);// 添加到顶层节点

}

3.编写代码, 实现按钮的 slot 函数

cpp 复制代码
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* item = new QTreeWidgetItem();
    item->setText(0, text);
    // 插入到选中节点的子结点中
    currentItem->addChild(item);

}


void Widget::on_pushButton_3_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);
    }
}

4.执行程序, 可以针对树形框进行编辑.

上述这几个控件相关的操作,数据都是在内从中保存的,无论在界面上做任何操作,重启运行程序,之前的数据就没有了

如果想让数据能够重启也不丢失,就需要编写更多的代码,把内存存储的数据获取到,写入到文件中,并且在下次运行的时候。从文件中加载数据!

相关推荐
amy_jork2 小时前
npm删除包
开发语言·javascript·ecmascript
浪成电火花2 小时前
(deepseek!)deepspeed中C++关联部分
开发语言·c++
艾伦~耶格尔3 小时前
【数据结构进阶】
java·开发语言·数据结构·学习·面试
杜子不疼.3 小时前
《Python列表和元组:从入门到花式操作指南》
开发语言·python
WYH2874 小时前
C#控制台输入(Read()、ReadKey()和ReadLine())
开发语言·c#
祈祷苍天赐我java之术4 小时前
Java 迭代器(Iterator)详解
java·开发语言
秋氘渔4 小时前
综合案例:Python 函数知识整合 — 学生成绩管理系统
开发语言·python
我命由我123454 小时前
软件开发 - 避免过多的 if-else 语句(使用策略模式、使用映射表、使用枚举、使用函数式编程)
java·开发语言·javascript·设计模式·java-ee·策略模式·js
long3165 小时前
java 策略模式 demo
java·开发语言·后端·spring·设计模式