MV结构下设置Qt表格的代理
目录
预备知识
模型
关联
刷新
示例
代理
模型
界面
结果
完整资料见:
所谓MV结构,是“model-view”(模型-视图)的简称。也就是说,表格的数据保存在model中,而视图由view实现。在我前面的很多博客,如设置QTableView的内容自动换行(2)_qstandarditem 文本换行显示-CSDN博客
如何截获QTableView的鼠标事件?_qtableview里面捕获鼠标移动事件-CSDN博客
QAbstractItemModel数据更新-CSDN博客
Qt如何正确的显示、修改表格(QTableView)的内容_qt tableview修改表格内容-CSDN博客
我已经花了很多笔墨描述Qt表格的软件设计方法。在本篇文章中,我将介绍如何编辑表格--表格代理。
预备知识
模型
模型用来存储表格数据。这个类通常派生自QAbstractTableModel。这个派生类的通常由如下几个部分组成:
成员变量:
m_data m_data通常是一个list,vector或者map等常见的数据结构。
用来存储数据。
以下为虚函数:
columnCount 列数
rowCount 行数
data 表格显示的内容
flags flags决定了各个单元格可否被编辑。假如不需要编辑表格,
也可以不重写此虚函数
headerData headerData返回值决定了各行/列标题名称
setData setData决定了编辑单元格以后,编辑结果如何影响m_data。
假如不需要编辑表格,也可以不重写此虚函数
关联
通过QTableView::setModel()建立与模型的关联
刷新
当m_data发生变化时,或者界面需要刷新时,刷新动作由dataChanged信号触发。很多人奇怪,怎么没看到对应dataChanged的槽函数?Qt内部已经将dataChanged与对应的槽函数做了关联,开发者不必操心,只要发出信号即可。
示例
代理
专门建立一个代理类
#include "EdtDelegate.h"EdtDelegate::EdtDelegate(int iMin, int iMax, QObject *parent): QStyledItemDelegate(parent)
{m_pIntVld = new QIntValidator(iMin, iMax, this);
}EdtDelegate::~EdtDelegate()
{}QWidget *EdtDelegate::createEditor(QWidget *parent,const QStyleOptionViewItem &/* option */,const QModelIndex &/* index */) const
{QLineEdit *editor = new QLineEdit(parent);editor->setValidator(m_pIntVld);return editor;
}void EdtDelegate::setEditorData(QWidget *editor,const QModelIndex &index) const
{QString qstrTxt = index.model()->data(index, Qt::DisplayRole).toString();QLineEdit *Edt = static_cast<QLineEdit*>(editor);Edt->setText(qstrTxt);
}void EdtDelegate::setModelData(QWidget *editor, QAbstractItemModel *model,const QModelIndex &index) const
{QLineEdit *edt = static_cast<QLineEdit*>(editor);auto qstrTxt = edt->text();model->setData(index, qstrTxt, Qt::EditRole);
}void EdtDelegate::updateEditorGeometry(QWidget *editor,const QStyleOptionViewItem &option, const QModelIndex &/* index */) const
{editor->setGeometry(option.rect);
}
#include "ComboDelegate.h"#include <QComboBox>ComboDelegate::ComboDelegate(QStringList qstrlst, QObject *parent): QStyledItemDelegate(parent), m_qstrlst(qstrlst){}QWidget *ComboDelegate::createEditor(QWidget *parent,const QStyleOptionViewItem &/* option */,const QModelIndex &/* index */) const{QComboBox *editor = new QComboBox(parent);editor->addItems(m_qstrlst);return editor;}void ComboDelegate::setEditorData(QWidget *editor,const QModelIndex &index) const{QString qstrTxt = index.model()->data(index, Qt::DisplayRole).toString();QComboBox *cmbBox = static_cast<QComboBox*>(editor);cmbBox->setCurrentText(qstrTxt);}void ComboDelegate::setModelData(QWidget *editor, QAbstractItemModel *model,const QModelIndex &index) const{QComboBox *cmbBox = static_cast<QComboBox*>(editor);auto qstrTxt = cmbBox->currentText();model->setData(index, qstrTxt, Qt::EditRole);}void ComboDelegate::updateEditorGeometry(QWidget *editor,const QStyleOptionViewItem &option, const QModelIndex &/* index */) const{editor->setGeometry(option.rect);}
这里有人会问,createEditor里面有new的动作,为什么没看到释放?createEditor返回一个指针。Qt内部有一套机制,在编辑结束后,自动释放该指针。
模型
#include "Model.h"//Model
Model::Model(int iTotalCol, QStringList qstrlstHeader, QList<int> lstNonEditableCols,QObject *parent) : QAbstractTableModel(parent),m_lstNonEditableCols(lstNonEditableCols),m_iTotalCol(iTotalCol), m_qstrlstHeader(qstrlstHeader)
{}int Model::rowCount(const QModelIndex &) const
{return m_data.size();
}int Model::columnCount(const QModelIndex &) const
{return m_iTotalCol;
}QVariant Model::data(const QModelIndex &index, int role) const
{int i = index.row(), j = index.column();if ((i >= 0) && (i < m_data.size())){if(m_data.at(i).size() > j){if(role == Qt::DisplayRole){//m_data的类型是QList<QStringList>,每一个QStringList对应表格里一行数据//m_data.at(i).at(j)对应的就是第i行,第j列的数据return m_data.at(i).at(j);}else if(role == Qt::TextAlignmentRole)return Qt::AlignCenter;else{}}else{return QString("");}}else{}return QVariant();
}QVariant Model::headerData(int section, Qt::Orientation orientation, int role) const
{if(role == Qt::DisplayRole){if(orientation == Qt::Horizontal)//横向排列的标题栏,也就是各个列的标题{if(m_qstrlstHeader.size() > section)return m_qstrlstHeader.at(section);else{return QString("");}}else{//纵向排列的标题栏,也就是各个行的标题return QString("");}}else if(role == Qt::TextAlignmentRole){//文字对齐方式设置为居中对齐return Qt::AlignCenter;}else{}return QAbstractTableModel::headerData(section, orientation, role);
}void Model::vSetData(QList<QStringList> & lstData)
{m_data.clear();m_data.append(lstData);//发出dataChanged信号,界面上才更新表格内容emit dataChanged(createIndex(0,0), createIndex(0, columnCount()-1));
}Qt::ItemFlags Model::flags(const QModelIndex &index) const
{if(m_lstNonEditableCols.contains(index.column()))//假如index对应的列是不可编辑的列return QAbstractTableModel::flags(index);else//假如index对应的列是可编辑的列,就给它添加ItemIsEditable属性return Qt::ItemIsEditable | QAbstractTableModel::flags(index);
}bool Model::setData(const QModelIndex &index, const QVariant &value, int role)
{if(role == Qt::EditRole){//编辑单元格之后,用编辑结果更新对应的m_dataint row = index.row(), col = index.column();QStringList qstrlst = m_data.at(row);qstrlst.replace(col, value.toString());m_data.replace(row, qstrlst);}return true;
}
界面
#include "mainwindow.h"
#include "ui_mainwindow.h"MainWindow::MainWindow(QWidget *parent) :QMainWindow(parent),ui(new Ui::MainWindow)
{ui->setupUi(this);m_pModel = new Model(4, {"1", "2", "3", "4"}, {0,1});ui->tableView->setModel(m_pModel);//setEditTriggers(QTableView::DoubleClicked);注明触发编辑单元格的方式是鼠标双击ui->tableView->setEditTriggers(QTableView::DoubleClicked);QList<QStringList> lstqstrlst;lstqstrlst<<QStringList{"a", "b", "c", "d"};//向表格中注入数据m_pModel->vSetData(lstqstrlst);m_scpCmbDelg.reset(new ComboDelegate({"a","b","c"}, this));//表格第2列采用combobox代理(其实是第3列,因为从0开始)ui->tableView->setItemDelegateForColumn(2, m_scpCmbDelg.data());m_scpEdtDelg.reset(new EdtDelegate(0,10, this));//表格第3列采用lineedit代理ui->tableView->setItemDelegateForColumn(3, m_scpEdtDelg.data());
}MainWindow::~MainWindow()
{delete ui;
}
结果
双击第一列、第二列,无法编辑单元格。但是双击第三列,可以编辑combobox;双击第四列,可以编辑lineedit:
qt代理,访问csdn金色熊族,获取完整信息
完整资料见:
【免费】介绍如何给Qt表格添加代理资源-CSDN文库
相关文章:
MV结构下设置Qt表格的代理
目录 预备知识 模型 关联 刷新 示例 代理 模型 界面 结果 完整资料见: 所谓MV结构,是“model-view”(模型-视图)的简称。也就是说,表格的数据保存在model中,而视图由view实现。在我前面的很多博客…...
二维数组 C++ 蓝桥杯
1.稀疏矩阵 #include<iostream> using namespace std;const int N 1e4 10; int a[N][N];int main() {int n, m; cin >> n >> m;for (int i 1; i < n; i) {for (int j 1; j < m; j) {cin >> a[i][j];}}for (int j m; j > 1; j--) {for (i…...
【Linux】文件描述符
初识文件 之前我们认识到当我们进行创建出一个空文件在磁盘上也是占用一部分空间的,因为文件的组成是由文件内容和文件属性共同构成。 文件内容属性,那我们对文件进行操作无外乎就是对内容和属性两个方面进行操作。 文件在磁盘上进行存储,…...
大语言模型的个性化综述 ——《Personalization of Large Language Models: A Survey》
摘要: 本文深入解读了论文“Personalization of Large Language Models: A Survey”,对大语言模型(LLMs)的个性化领域进行了全面剖析。通过详细阐述个性化的基础概念、分类体系、技术方法、评估指标以及应用实践,揭示了…...
AI 编程工具—Cursor进阶使用 Agent模式
AI 编程工具—Cursor进阶使用 Agent模式 我们在使用Cursor 的是有,在Composer 模式下,提交的是有两种模式 Normal 模式,也就是默认的模式Agent 模式Agent 模式可以帮我们生成代码文件,执行程序,安装依赖,并且完成一些列的工作 这里有个点很重要就是在Agent 模式下,Cur…...
【AI大模型】DeepSeek API大模型接口实现
目录 一、DeepSeek发展历程 2023 年:创立与核心技术突破 2024 年:开源生态与行业落地 2025 年:多模态与全球化布局 性能对齐 OpenAI-o1 正式版 二、API接口调用 1.DeepSeek-V3模型调用 2.DeepSeek-R1模型调用 三、本地化部署接口调…...
Qt展厅播放器/多媒体播放器/中控播放器/帧同步播放器/硬解播放器/监控播放器
一、前言说明 音视频开发除了应用在安防监控、视频网站、各种流媒体app开发之外,还有一个小众的市场,那就是多媒体展厅场景,这个场景目前处于垄断地位的软件是HirenderS3,做的非常早而且非常全面,都是通用的需求&…...
Kafka分区策略实现
引言 Kafka 的分区策略决定了生产者发送的消息会被分配到哪个分区中,合理的分区策略有助于实现负载均衡、提高消息处理效率以及满足特定的业务需求。 轮询策略(默认) 轮询策略是 Kafka 默认的分区策略(当消息没有指定键时&…...
【归属地】批量号码归属地查询按城市高速的分流,基于WPF的解决方案
在现代商业活动中,企业为了提高营销效果和资源利用效率,需要针对不同地区的市场特点开展精准营销。通过批量号码归属地查询并按城市分流,可以为企业的营销决策提供有力支持。 短信营销:一家连锁餐饮企业计划开展促销活动…...
为AI聊天工具添加一个知识系统 之78 详细设计之19 正则表达式 之6
本文要点 要点 本项目设计的正则表达式 是一个 动态正则匹配框架。它是一个谓词系统:谓词 是运动,主语是“维度”,表语是 语言处理。主语的一个 双动结构。 Reg三大功能 语法验证、语义检查和 语用检验,三者 :语义约…...
使用Java操作Redis数据类型的详解指南
SEO Meta Description: 详细介绍如何使用Java操作Redis的各种数据类型,包括字符串、哈希、列表、集合和有序集合,提供代码示例和最佳实践。 介绍 Redis是一种开源的内存数据结构存储,用作数据库、缓存和消息代理。它支持多种数据结构&#…...
一表总结 Java 的3种设计模式与6大设计原则
设计模式通常分为三大类:创建型、结构型和行为型。 创建型模式:主要用于解决对象创建问题结构型模式:主要用于解决对象组合问题行为型模式:主要用于解决对象之间的交互问题 创建型模式 创建型模式关注于对象的创建机制…...
Hive on Spark优化
文章目录 第1章集群环境概述1.1 集群配置概述1.2 集群规划概述 第2章 Yarn配置2.1 Yarn配置说明2.2 Yarn配置实操 第3章 Spark配置3.1 Executor配置说明3.1.1 Executor CPU核数配置3.1.2 Executor内存配置3.1.3 Executor个数配置 3.2 Driver配置说明3.3 Spark配置实操 第4章 Hi…...
Java集合面试总结(题目来源JavaGuide)
问题1:说说 List,Set,Map 三者的区别? 在 Java 中,List、Set 和 Map 是最常用的集合框架(Collection Framework)接口,它们的主要区别如下: 1. List(列表) 特点…...
计算机网络 应用层 笔记1(C/S模型,P2P模型,FTP协议)
应用层概述: 功能: 常见协议 应用层与其他层的关系 网络应用模型 C/S模型: 优点 缺点 P2P模型: 优点 缺点 DNS系统: 基本功能 系统架构 域名空间: DNS 服务器 根服务器: 顶级域…...
ES6基础内容
ES 全称 EcmaScript ,是脚本语言的规范,而平时经常编写的 JavaScript 是 EcmaScript 的一种实现,所以 ES 新特性其实指的就是 JavaScript 的新特性。 一、 let变量声明和声明特性 1.1 变量声明 <!DOCTYPE html> <html lang"en">…...
DeepSeek本地部署的一些使用体会
春节期间我也尝试了一下Deepseek的本地部署,方案选用了Ollama Chatbox或AnythingLLM。Chatbox里有很多有意思的“助手”,而AnythingLLM支持本地知识库。 网上教程很多,总的来说还是很方便的,不需要费太多脑子。甚至可以这么说&a…...
鲸鱼算法 matlab pso
算法原理 鲸鱼优化算法的核心思想是通过模拟座头鲸的捕食过程来进行搜索和优化。座头鲸在捕猎时会围绕猎物游动并产生气泡网,迫使猎物聚集。这一行为被用来设计搜索策略,使算法能够有效地找到全局最优解。 算法步骤 初始化:随机生成一…...
013-51单片机红外遥控器模拟控制空调,自动制冷制热定时开关
主要功能是通过红外遥控器模拟控制空调,可以实现根据环境温度制冷和制热,能够通过遥控器设定温度,可以定时开关空调。 1.硬件介绍 硬件是我自己设计的一个通用的51单片机开发平台,可以根据需要自行焊接模块,这是用立创…...
在Vue3 + Vite 项目中使用 Tailwind CSS 4.0
文章目录 首先是我的package.json根据官网步骤VS Code安装插件验证是否引入成功参考资料 首先是我的package.json {"name": "aplumweb","private": true,"version": "0.0.0","type": "module","s…...
YOLOv13开箱即用镜像体验:简单几步,完成你的第一个AI检测项目
YOLOv13开箱即用镜像体验:简单几步,完成你的第一个AI检测项目 1. 为什么选择YOLOv13官版镜像? 1.1 传统部署的痛点 在目标检测领域,YOLO系列一直是开发者的首选。但传统部署方式往往让人望而却步: 环境配置复杂&am…...
AMD Ryzen平台硬件调试与性能优化实战指南:基于SMUDebugTool的系统级解决方案
AMD Ryzen平台硬件调试与性能优化实战指南:基于SMUDebugTool的系统级解决方案 【免费下载链接】SMUDebugTool A dedicated tool to help write/read various parameters of Ryzen-based systems, such as manual overclock, SMU, PCI, CPUID, MSR and Power Table. …...
破局RePKG使用困境:7个让效率倍增的创新工作流
破局RePKG使用困境:7个让效率倍增的创新工作流 【免费下载链接】repkg Wallpaper engine PKG extractor/TEX to image converter 项目地址: https://gitcode.com/gh_mirrors/re/repkg 认知重构:重新理解壁纸资源处理的本质 1.1 三维困境模型&…...
Python入门实战:调用MogFace-large完成你的第一个人脸检测程序
Python入门实战:调用MogFace-large完成你的第一个人脸检测程序 你是不是对AI人脸检测感到好奇,但又觉得它离自己很远,需要高深的数学和复杂的代码?今天,我们就来打破这个迷思。我将带你用Python,从一个纯新…...
【信号处理实战】从原理到代码:手把手实现三次样条插值
1. 三次样条插值:从数学定义到生活场景 想象你正在用一根柔软的弹性尺子连接一组图钉,这些图钉固定在木板上代表你的数据点。这根尺子需要光滑地穿过每一个图钉,同时保持自然的弯曲形态——这就是三次样条插值要解决的问题。作为信号处理中最…...
嵌入式系统内存管理技术与实践
嵌入式系统内存管理的工程实践1. 嵌入式内存管理概述嵌入式系统的内存管理直接决定了系统的三个关键特性:稳定性、实时性和功耗表现。与通用计算系统不同,嵌入式环境对内存使用有着更严格的约束条件,这要求工程师必须掌握专业的内存管理技术。…...
告别终端命令:Applite如何让macOS应用管理变得轻松有趣
告别终端命令:Applite如何让macOS应用管理变得轻松有趣 【免费下载链接】Applite User-friendly GUI macOS application for Homebrew Casks 项目地址: https://gitcode.com/gh_mirrors/ap/Applite 如果你曾因复杂的终端命令而对Homebrew望而却步,…...
网易云音乐无损解析:从零打造个人音乐库的终极指南
网易云音乐无损解析:从零打造个人音乐库的终极指南 【免费下载链接】Netease_url 网易云无损解析 项目地址: https://gitcode.com/gh_mirrors/ne/Netease_url 还在为网易云音乐无法下载无损音质而烦恼吗?想要建立属于自己的高品质音乐收藏库吗&am…...
Spring Cloud Hystrix 详细示-元一软件
Hystrix 是 Spring Cloud 中实现服务熔断、降级、隔离的核心组件,用于解决微服务架构中的雪崩效应,核心是快速失败、优雅降级、自动恢复。以下从环境搭建、基础使用、高级配置、Feign 整合、监控5 个维度提供完整示例。一、项目环境准备1. 依赖引入&…...
OpenClaw技能开发入门:为nanobot编写自定义文件处理器
OpenClaw技能开发入门:为nanobot编写自定义文件处理器 1. 为什么需要自定义技能 去年夏天,我发现自己每周都要花两小时手动整理项目文档——把分散在各处的Markdown文件合并、去重、重新编号。当我第三次在重复劳动中睡着时,终于决定用Open…...
