C++ Qt开发:TableView与TreeView组件联动
Qt 是一个跨平台C++图形界面开发库,利用Qt可以快速开发跨平台窗体应用程序,在Qt中我们可以通过拖拽的方式将不同组件放到指定的位置,实现图形化开发极大的方便了开发效率,本章将重点介绍TableView与TreeView组件联动的常用方法及灵活运用。
本章我们继续实现表格的联动效果,当读者点击TableView或TreeView中的某一行时,我们让其实现自动跟随功能,且当用户修改行中特定数据时也让其动态的跟随改变,首先绘制一个主界面如图,分别放置两个组件框,底部保留两个按钮,按钮1用于该表表格的行列个数,按钮2则用于设置TableView表格表头参数,整个表格我们将其设置为可编辑状态。

在函数中我们需要定义一个QStandardItemModel模型,这个模型的作用在之前的文章中有具体介绍,它是一个灵活且功能强大的模型类,适用于需要自定义数据结构、支持编辑、表头等功能的场景。通常用于与视图组件(如 QTableView、QTreeView 等)一起使用。它提供了一个表格结构,可以包含行和列,每个单元格可以存储一个 QStandardItem 对象。
这里的QStandardItemModel只适用于将两个不同类型的组件进行关联,简单点来说就是将两个组件指向同一个数据容器内,这样当用户修改任意一个组件内的数据另一个组件也会同步发生变更,但要想实现联动则还需要使用QItemSelectionModel模型,它负责跟踪哪些项被选中,以及在模型中项的选择状态发生变化时发出信号。
以下是 QItemSelectionModel 的一些重要特性和方法:
- 选择项: 负责管理模型中的项的选择状态,可以单独选择项、选定范围内的项或清除所有选择项。
- 信号: 当选择状态发生变化时,
QItemSelectionModel会发出相应的信号,如selectionChanged信号。 - 选择模式: 提供多种选择模式,包括单选、多选、扩展选择等,可通过设置
SelectionMode进行配置。 - 选择策略: 提供多种选择策略,用于定义选择行为,如
SelectItems、SelectRows、SelectColumns等。 - 与视图的集成: 通常与
QTableView、QTreeView等视图组件结合使用,以实现对视图中项的选择操作。
该组件是实现模型-视图架构中选择的关键组件。通过它,可以轻松管理和操作模型中的项的选择状态,实现各种灵活的用户交互。下面是 QItemSelectionModel 类的一些主要方法:
| 方法 | 描述 |
|---|---|
QItemSelectionModel(QAbstractItemModel *model, QObject *parent = nullptr) |
构造函数,创建一个与指定模型关联的 QItemSelectionModel 对象。 |
QModelIndexList selectedIndexes() const |
获取当前被选中的项的索引列表。 |
void clear() |
清除所有的选择项。 |
void setSelectionMode(QItemSelectionModel::SelectionFlags mode) |
设置选择模式,可以选择多个项、单个项等。 |
void setSelectionBehavior(QItemSelectionModel::SelectionBehavior behavior) |
设置选择策略,如选择单个项、选择整行、选择整列等。 |
void select(const QModelIndex &topLeft, const QModelIndex &bottomRight, QItemSelectionModel::SelectionFlags command) |
在指定范围内进行选择操作,使用 SelectionFlags 定义选择操作。 |
void selectionChanged(const QItemSelection &selected, const QItemSelection &deselected) |
当选择状态发生变化时发出的信号,可以通过连接这个信号来处理选择状态变化的事件。 |
bool hasSelection() const |
判断是否有选中的项。 |
上述方法提供了管理选择项的一些基本操作,包括清除选择、获取选中项的索引、设置选择模式和策略,以及在指定范围内进行选择操作。
在MainWindow构造函数中,我们以此执行如下关键部分,来实现对主界面的初始化工作;
创建模型和选择模型
首先创建一个包含4行5列的 QStandardItemModel 模型,并为其创建了一个 QItemSelectionModel 选择模型。
model = new QStandardItemModel(4, 5, this);
selection = new QItemSelectionModel(model);
关联到 tableView 和 treeView
将模型和选择模型关联到 tableView 和 treeView 上,这样它们会共享同一份数据模型,也就是无论两个组件哪一个发生变化均会影响双方组件中的内容。
ui->tableView->setModel(model);
ui->tableView->setSelectionModel(selection);
ui->treeView->setModel(model);
ui->treeView->setSelectionModel(selection);
添加表头与初始化数据
创建一个包含列名的 HeaderList 字符串列表,并将其设置为模型的水平表头标签。继续创建一个包含三个字符串列表的数组 DataList,每个列表代表一行数据。然后使用嵌套的循环遍历数组,将数据逐个添加到模型中。
QStringList HeaderList;
HeaderList << "序号" << "姓名" << "年龄" << "性别" << "婚否";
model->setHorizontalHeaderLabels(HeaderList);
QStringList DataList[3];
QStandardItem *Item;
DataList[0] << "1001" << "admin" << "24" << "男" << "是";
DataList[1] << "1002" << "lyshark" << "23" << "男" << "否";
DataList[2] << "1003" << "lucy" << "37" << "女" << "是";
通过循环添加数据到模型
使用两个循环,外层循环遍历数组,内层循环遍历每个数组中的元素,创建 QStandardItem 对象并将其添加到模型的相应位置。
cppCopy codeint Array_Length = DataList->length(); // 获取每个数组中元素数
int Array_Count = sizeof(DataList) / sizeof(DataList[0]); // 获取数组个数
for(int x=0; x<Array_Count; x++)
{
for(int y=0; y<Array_Length; y++)
{
Item = new QStandardItem(DataList[x][y]);
model->setItem(x, y, Item);
}
}
如上这段代码初始化了一个包含表头和数据的 QStandardItemModel 模型,然后将模型和选择模型关联到 tableView 和 treeView 上,最后通过循环将数据逐个添加到模型中。这样就创建了一个主窗口,其中包含了一个表格视图和一个树形视图,它们共享相同的数据模型。如下图所示;

DialogSize.ui
接着来看on_pushButton_clicked按钮是如何实现的,该按钮主要用于实现改变表格行与列,当点击后则会弹出一个DialogSize自定义对话框,至于对话框是如何添加的在之前的文章中已经详细介绍过了。
在如下代码中我们通过model->rowCount()以及model->columnCount()获取到父UI界面中tableView表格的行列数,并通过ptr->setRowColumn将这些数据设置到了子对话框的编辑框上面,而ptr->columnCount()则用于接收子对话框的返回值,并将其动态设置到对应的模型中;
void MainWindow::on_pushButton_clicked()
{
// //模态对话框,动态创建,用过后删除
DialogSize *ptr = new DialogSize(this); // 创建一个对话框
Qt::WindowFlags flags = ptr->windowFlags(); // 需要获取返回值
ptr->setWindowFlags(flags | Qt::MSWindowsFixedSizeDialogHint); // 设置对话框固定大小
ptr->setRowColumn(model->rowCount(),model->columnCount()); // 对话框数据初始化
int ref = ptr->exec(); // 以模态方式显示对话框
if (ref==QDialog::Accepted) // OK键被按下,对话框关闭
{
// 当BtnOk被按下时,则设置对话框中的数据
int cols=ptr->columnCount();
model->setColumnCount(cols);
int rows=ptr->rowCount();
model->setRowCount(rows);
}
// 最后删除释放对话框句柄
delete ptr;
}
接着来看下子对话框DialogSize做了什么,在对话框代码中rowCount()是给主窗体调用的函数其功能是获取到当前对话框中spinBoxRow组件中的数值,而columnCount()同理用于得到spinBoxColumn组件中的数值,最后的setRowColumn()则是用于接收主窗体的船只,并设置到对应的子对话框上的SpinBox组件内,其代码如下;
DialogSize::DialogSize(QWidget *parent) :QDialog(parent),ui(new Ui::DialogSize)
{
ui->setupUi(this);
}
DialogSize::~DialogSize()
{
delete ui;
}
// 主窗体调用获取当前行数
int DialogSize::rowCount()
{
return ui->spinBoxRow->value();
}
// 主窗体调用获取当前列数
int DialogSize::columnCount()
{
return ui->spinBoxColumn->value();
}
// 设置主窗体中的TableView行数与列数
void DialogSize::setRowColumn(int row, int column)
{
ui->spinBoxRow->setValue(row);
ui->spinBoxColumn->setValue(column);
}
运行程序,并点击左侧第一个按钮,此时我们可以将表格设置为6*6的矩阵,如下图所示;

DIalogHead.ui
对于第二个按钮on_pushButton_2_clicked的功能实现与第一个按钮完全一致,该按钮主要实现对父窗体中TableView的表头进行重新设置,在弹出对话框之前,需要将当前表头元素复制到strList列表容器内,并通过使用子对话框中的ptr->setHeaderList将其拷贝到子对话框中,并通过QDialog::Accepted等待对话框按下修改按钮,如下代码所示;
void MainWindow::on_pushButton_2_clicked()
{
DialogHead *ptr = new DialogHead(this);
Qt::WindowFlags flags = ptr->windowFlags();
ptr->setWindowFlags(flags | Qt::MSWindowsFixedSizeDialogHint);
// 如果表头列数变化,则从新初始化
if(ptr->headerList().count() != model->columnCount())
{
QStringList strList;
// 获取现有的表头标题
for (int i=0;i<model->columnCount();i++)
{
strList.append(model->headerData(i,Qt::Horizontal,Qt::DisplayRole).toString());
}
// 用于对话框初始化显示
ptr->setHeaderList(strList);
}
// 调用弹窗
int ref = ptr->exec();
if(ref==QDialog::Accepted)
{
// 获取对话框上修改后的StringList
QStringList strList=ptr->headerList();
// 设置模型的表头标题
model->setHorizontalHeaderLabels(strList);
}
delete ptr;
}
当读者按下了修改按钮之后,由于通过ui->listView->setModel(model)已经与父窗体建立了关联,则此时通过model->setStringList(headers)就可以实现对父窗体中数据的修改,代码如下所示;
DialogHead::DialogHead(QWidget *parent) :QDialog(parent),ui(new Ui::DialogHead)
{
ui->setupUi(this);
model = new QStringListModel;
ui->listView->setModel(model);
}
DialogHead::~DialogHead()
{
delete ui;
}
// 设置当前listView中的数据
void DialogHead::setHeaderList(QStringList &headers)
{
model->setStringList(headers);
}
// 返回当前的表头
QStringList DialogHead::headerList()
{
return model->stringList();
}
程序运行后,读者可以先将表格的行与列修改为7*7,接着再通过设置表头的方式更新表头,效果如下;

C++ Qt开发:TableView与TreeView组件联动的更多相关文章
- C/C++ Qt 数据库与TreeView组件绑定
在上一篇博文<C/C++ Qt 数据库QSql增删改查组件应用>介绍了Qt中如何使用SQL操作函数,并实现了对数据库的增删改查等基本功能,从本篇开始将实现数据库与View组件的绑定,通过数 ...
- 基于QT开发的第三方库
基于Qt开发的第三方库 分类: Qt2014-02-12 11:34 1738人阅读 评论(0) 收藏 举报 QT第三方库 目录(?)[+] 文章来源:http://blog.csdn.net ...
- win使用MSYS2安装Qt开发环境
原文链接 MSYS2 下载地址: pacman的具体用法 有pacman的具体使用方法.我们首先对系统升级 我们首先对系统升级 pacman -Syu 就会检测整个系统可以升级的组件,并自动下载安装, ...
- 【应用笔记】【AN005】Qt开发环境下基于RS485的4-20mA电流采集
简介 4-20mA电流环具有广泛的应用前景,在许多行业中都发挥着重要作用.本文主要介绍在Qt开发环境下基于RS485实现4-20mA电流采集,实现WINDOWS平台对数据的采集.分析及显示. 系统组成 ...
- Qt开发环境下载和安装
Qt是跨平台的图形开发库,目前由Digia全资子公司 Qt Company 独立运营,官方网址: http://www.qt.io/ 也可以访问Qt项目域名:http://qt-project.org ...
- Qt开发北斗定位系统融合百度地图API及Qt程序打包发布
Qt开发北斗定位系统融合百度地图API及Qt程序打包发布 1.上位机介绍 最近有个接了一个小型项目,内容很简单,就是解析北斗GPS的串口数据然后输出经纬度,但接过来觉得太简单,就发挥了主观能动性,增加 ...
- CAD控件:QT开发使用控件入门
1. 环境搭建: 3 1.1. 安装Qt 3 1.2. 安装Microsoft Windows SDK的调试包 6 2. QT中使用MxDraw控件 7 1.3. 引入控件 7 3. 打开DWG文件 ...
- QT开发环境的建立以及QTE4.6.3、tslib1.4的移植过程
1.首先是建立Linux开发环境1.1.在windowsXP下安装博创公司提供的虚拟机软件VMware Workstation,版本为VMware-workstation-full-7.0.1-227 ...
- 基于arm的嵌入式QT开发(课程设计)
一. 项目要求 配置QT5.7基于x86及arm 等两种CPU架构的调试及开发环境: 移植arm编译后的QT5.7及屏幕校准工具tslib1.4至CORTEX ARM9实验平台: 开发基于QT5.7的 ...
- Qt高仿Excel表格组件-支持冻结列、冻结行、内容自适应和合并单元格
目录 一.概述 二.效果展示 三.实现思路 1.冻结行.冻结列 2.行高自适应 3.蚂蚁线 四.测试代码 1.添加表格数据 2.设置冻结行.列 3.行高.列宽 4.单元格背景色 5.单元格文字 6.其 ...
随机推荐
- tomcat配置域名绑定项目
有时候我们需要根据访问的不同域名,对应tomcat中不同的项目例如:一个网站同时做了两套,pc版和手机版.手机版对应的域名是m.we-going.com,就需要在tomcat配置文件中加入以下代码:& ...
- Fabric 2.x 智能合约开发记录
表象:Return schema invalid. required items must be unique [recovered] 虽然 Fabric v2.2 已经发布了很久了,但之前因为项目历 ...
- 3天上手Ascend C编程丨通过Ascend C编程范式实现一个算子实例
本文分享自华为云社区<3天上手Ascend C编程 | Day2 通过Ascend C编程范式实现一个算子实例>,作者:昇腾CANN . 一.Ascend C编程范式 Ascend C编程 ...
- #POWERBI_指标监控(第二部分,周期内下降天数及日期明细)
在指标监控的第一部分文章中,我们已经讲了,如何用DAX去查询一段周期内连续下降或者上升指标. 需要复习的同学可以点击下方链接: https://www.cnblogs.com/simone331/p/ ...
- 【Python进阶-PyQt5】00搭建PyQt5环境
1.创建独立开发虚拟环境 1.1虚拟环境简介 我们编写的程序,有时用到的Python库是不一样的,比如说开发桌面应用程序我们主要用到PyQt5相关的Python库.开发Web应用程序我们主要用到Dja ...
- 在deepin上使用Fleet开发SpringBoot 3.0.0项目
前言 Fleet被称为是由 JetBrains 打造的下一代 IDE,目前出于公测状态,可以免费下载使用. SpringBoot 3.0.0最小支持是JDK 17,这或许是对于JDK8的断舍离迈出的重 ...
- Redis系列之——Redis介绍安装配置
文章目录 第一章 redis初识 1.1 Redis是什么 1.2 Redis特性(8个) 1.3 Redis单机安装 1.3.1下载安装 1.3.2三种启动方式 1.3.2.1 最简启动 1.3.2 ...
- oracle 命令4 热备份
热备份:不停数据库,一定范围内(内存写满后,用户操作挂起),不影响用户使用.数据库开着,时刻变化,因此热备份通过以下手段保持一致性:1.开启归档2.备份前,通知数据库,把文件锁定,在备份未完成前,不操 ...
- PolarD&N2023秋季个人挑战—Crypto全解
EasyRSA (额..这个题看错了不是挑战赛的.这里当做好题记录下来了) 题目信息:500 分 5 Polar币 from Crypto.Util.number import bytes_to_lo ...
- Vue之属性
Vue中的属性:举例 看一下就明白了 <!DOCTYPE html> <html lang="en"> <head> <meta char ...