Qt 模型、视图、代理
提示文章写完后目录可以自动生成如何生成可参考右边的帮助文档文章目录前言一、MVD的理解二、代码1.实现的功能2.效果3.代码示例总结前言模型和视图的主要作用就是实现数据显示和存储分离Qt通过MVD模型、视图、代理实现了这种功能。一、MVD的理解模型 M:模型类定义了标准的接口供视图View和委托(Delegate)来访问数据。数据本身不需要存储在模型中;它可以保存在由单独的类、文件、数据库或其它应用程序组件提供的数据结构或存储库中。模型对数据进行封装例如封装成List、Tree、Table等并提供了数据的访问接口例如data()、setData()等。有的简单的数据可以保存在Model中复杂的可以保存在类、文件、数据库等组件中。 例如QStringListModel类可以保存QString数据QFileSystemModel类可以组织、封装文件系统数据并提供访问接口QSqlQueryModel、QSqlTableModel和QSqlRelationalTableModel组织、封装数据库数据并提供数据的访问接口。视图 V:视图提供了一个标准接口通过信号和槽机制与模型进交互操作使子类能够随时更新其模型的更改。视图类负责人眼能看到的一些属性包括数据的绘制管理表头、数据项的选择网格的显示隐藏以及行高列宽的设置等。另外提供信号当交互操作时通知模型更新数据等。代理D:代理为模型/视图架构中的代理提供了接口和通用函数。代理在视图中显示单独的数据项并且处理模型数据的编辑。代理提供了访问模型和视图的接口当要实现复杂功能的显示时例如表格中显示下拉框、按钮、进度条等只靠模型和视图不能实现需要借助代理来实现。代理可以通过创建编辑器编辑器可以是下拉框、按钮或者进度条等并实现代理提供的虚函数来实现这些功能。二、代码1.实现的功能该demo使用QTableView、QStandardItemModel、QStyledItemDelegate类创建了表格并表格中自定义了QComboBox、QSpinBox、QPushButton、QProgressBar等其中按钮关联槽函数获取表格item的值并打印并且创建了定时器在超时槽函数中更新进度条的值。实现时代理我选择了QStyledItemDelegate类因为更新进度条时需要重绘进度条样式。若只有交互组件不用重绘组件样式也可选用QItemDelegate。2.效果3.代码示例3.1 Mainwindow.h头文件代码示例#ifndefMAINWINDOW_H#defineMAINWINDOW_H#includeQMainWindow#includeQTableView#includeQStandardItemModel#includeMyitemydelegate.h#includeQVBoxLayout#includeQTextBrowser#includeQTimernamespaceUi{classMainWindow;}classMainWindow:publicQMainWindow{Q_OBJECTpublic:explicitMainWindow(QWidget*parent0);~MainWindow();private:Ui::MainWindow*ui;QString tableInitData[4][5]{{张一,男,21,10,获取},{张二,男,22,20,获取},{张三,女,23,30,获取},{张四,女,24,40,获取}};QTimer*updateBarTimer;QWidget*centralWidget;QTableView*tableView;QStandardItemModel*itemModel;MyItemyDelegate*delegate;QVBoxLayout*widgetVLayout;QTextBrowser*displayBrowser;voidinitTable();publicslots:voidtableBtnClickedSlot(introw);voidupdateProgressBarData();};#endif// MAINWINDOW_H3.2 Mainwindow.cpp文件代码示例#includemainwindow.h#includeui_mainwindow.h#includeQDebugMainWindow::MainWindow(QWidget*parent):QMainWindow(parent),ui(newUi::MainWindow){ui-setupUi(this);initTable();}MainWindow::~MainWindow(){deleteui;}voidMainWindow::initTable(){/*新建对象*/updateBarTimernewQTimer;centralWidgetnewQWidget(this);tableViewnewQTableView;itemModelnewQStandardItemModel;delegatenewMyItemyDelegate;widgetVLayoutnewQVBoxLayout;displayBrowsernewQTextBrowser;/*设置表格格式*/itemModel-setColumnCount(5);itemModel-setRowCount(4);itemModel-setHeaderData(0,Qt::Horizontal,姓名);itemModel-setHeaderData(1,Qt::Horizontal,性别);itemModel-setHeaderData(2,Qt::Horizontal,年龄);itemModel-setHeaderData(3,Qt::Horizontal,学习进度);itemModel-setHeaderData(4,Qt::Horizontal,获取进度);/*表格设置模型和代理*/tableView-setModel(itemModel);tableView-setItemDelegate(delegate);/*布局*/widgetVLayout-addWidget(tableView);widgetVLayout-addWidget(displayBrowser);centralWidget-setLayout(widgetVLayout);this-setCentralWidget(centralWidget);/*表格item初始化*/for(inti0;i4;i){for(intj0;j5;j){itemModel-setItem(i,j,newQStandardItem(tableInitData[i][j]));itemModel-item(i,j)-setTextAlignment(Qt::AlignCenter);}}connect(delegate,SIGNAL(clicked(int)),this,SLOT(tableBtnClickedSlot(int)));connect(updateBarTimer,SIGNAL(timeout()),this,SLOT(updateProgressBarData()));updateBarTimer-start(1000);}/*表格中按钮的响应槽函数*/voidMainWindow::tableBtnClickedSlot(introw){displayBrowser-clear();QString itemName[4]{姓名,性别,年龄,学习进度};for(inti0;i4;i){displayBrowser-append(itemName[i]itemModel-item(row,i)-text());}}/*定时器超时函数更新进度条*/voidMainWindow::updateProgressBarData(){for(inti0;i4;i){intsetData(itemModel-item(i,3)-text().toInt()5)%100;itemModel-setData(itemModel-index(i,3),setData);}}3.3 MyItemyDelegate.h文件代码示例在使用代理时有几个虚函数需要在子类中重新实现具体可根据需要去实现例如当需要绘制样式时需要实现paint()函数否则不用实现。#ifndefMYITEMYDELEGATE_H#defineMYITEMYDELEGATE_H#includeQObject#includeQPushButton#includeQComboBox#includeQSpinBox#includeQProgressBar#includeQStyledItemDelegateclassMyItemyDelegate:publicQStyledItemDelegate{Q_OBJECTpublic:explicitMyItemyDelegate(QObject*parentnullptr);~MyItemyDelegate();/*当需要创建自定义交互编辑器时需要实现下面这几个函数*/QWidget*createEditor(QWidget*parent,constQStyleOptionViewItemoption,constQModelIndexindex)constoverride;voidsetEditorData(QWidget*editor,constQModelIndexindex)constoverride;voidsetModelData(QWidget*editor,QAbstractItemModel*model,constQModelIndexindex)constoverride;voidupdateEditorGeometry(QWidget*editor,constQStyleOptionViewItemoption,constQModelIndexindex)constoverride;/*当需要绘制样式时需要重新实现paint()函数*/voidpaint(QPainter*painter,constQStyleOptionViewItemoption,constQModelIndexindex)const;/*当需要过滤操作事件例如按钮点击事件时需要重新实现editorEvent()函数*/booleditorEvent(QEvent*event,QAbstractItemModel*model,constQStyleOptionViewItemoption,constQModelIndexindex);signals:voidclicked(introw);};#endif// MYITEMYDELEGATE_H3.4MyItemyDelegate.cpp文件代码示例#includeMyitemydelegate.h#includeQApplication#includeQMouseEvent#includeQDebugMyItemyDelegate::MyItemyDelegate(QObject*parent):QStyledItemDelegate(parent){}MyItemyDelegate::~MyItemyDelegate(){}QWidget*MyItemyDelegate::createEditor(QWidget*parent,constQStyleOptionViewItemoption,constQModelIndexindex)const{if(index.column()1)/*性别*/{QComboBox*tableComBoxnewQComboBox(parent);tableComBox-addItem(男);tableComBox-addItem(女);returntableComBox;}elseif(index.column()2)/*年龄*/{QSpinBox*tableSpinBoxnewQSpinBox(parent);tableSpinBox-setFrame(false);tableSpinBox-setMinimum(0);tableSpinBox-setMaximum(100);returntableSpinBox;}elseif(index.column()3)/*进度*/{returnnullptr;}elseif(index.column()4)/*控制按钮*/{returnnullptr;}returnQStyledItemDelegate::createEditor(parent,option,index);}voidMyItemyDelegate::setEditorData(QWidget*editor,constQModelIndexindex)const{if(index.column()1)/*性别*/{QString valueindex.model()-data(index,Qt::EditRole).toString();QComboBox*comboBoxstatic_castQComboBox*(editor);inttindexcomboBox-findText(value);comboBox-setCurrentIndex(tindex);}elseif(index.column()2)/*年龄*/{intvalueindex.model()-data(index,Qt::EditRole).toInt();QSpinBox*spinBoxstatic_castQSpinBox*(editor);spinBox-setValue(value);}else{QStyledItemDelegate::setEditorData(editor,index);}}voidMyItemyDelegate::setModelData(QWidget*editor,QAbstractItemModel*model,constQModelIndexindex)const{if(index.column()1)/*性别*/{QComboBox*comboBoxstatic_castQComboBox*(editor);QString textcomboBox-currentText();model-setData(index,text,Qt::EditRole);}elseif(index.column()2)/*年龄*/{QSpinBox*spinBoxstatic_castQSpinBox*(editor);spinBox-interpretText();intvaluespinBox-value();model-setData(index,value,Qt::EditRole);}else{QStyledItemDelegate::setModelData(editor,model,index);}}voidMyItemyDelegate::updateEditorGeometry(QWidget*editor,constQStyleOptionViewItemoption,constQModelIndexindex)const{Q_UNUSED(index)editor-setGeometry(option.rect);}voidMyItemyDelegate::paint(QPainter*painter,constQStyleOptionViewItemoption,constQModelIndexindex)const{if(index.isValid()(index.column()3)){QStyleOptionProgressBar*progressBarnewQStyleOptionProgressBar;progressBar-rectoption.rect;progressBar-progressindex.data().toInt();progressBar-maximum100;progressBar-minimum0;progressBar-textQString::number(progressBar-progress)%;progressBar-textVisibletrue;progressBar-textAlignmentQt::AlignCenter;QApplication::style()-drawControl(QStyle::CE_ProgressBar,progressBar,painter);}elseif(index.isValid()(index.column()4)){QStyleOptionButton*btnStylenewQStyleOptionButton;btnStyle-text获取;btnStyle-rectoption.rect;btnStyle-stateQStyle::State_Enabled;QPushButton btn;btn.style()-drawControl(QStyle::CE_PushButton,btnStyle,painter,btn);}else{QStyledItemDelegate::paint(painter,option,index);}}boolMyItemyDelegate::editorEvent(QEvent*event,QAbstractItemModel*model,constQStyleOptionViewItemoption,constQModelIndexindex){Q_UNUSED(model);QMouseEvent*mouseEventstatic_castQMouseEvent*(event);if(option.rect.contains(mouseEvent-pos())){if((event-type()QEvent::MouseButtonPress)(index.column()4)){emitclicked(index.row());}}returnQStyledItemDelegate::editorEvent(event,model,option,index);}总结以上就是今天要讲的内容本文以QTableView为例仅仅简单介绍模型、视图、代理的简单使用方法Qt还提供了其它丰富的类感兴趣可继续深入学习。

相关新闻

grunt-responsive-images插件架构解析:深入理解任务执行流程与扩展机制

grunt-responsive-images插件架构解析:深入理解任务执行流程与扩展机制

grunt-responsive-images插件架构解析:深入理解任务执行流程与扩展机制 【免费下载链接】grunt-responsive-images Produce images at different sizes for responsive websites. 项目地址: https://gitcode.com/gh_mirrors/gr/grunt-responsive-images 在现…

2026/7/21 15:59:40阅读更多 →
ChatGLM-finetune-LoRA进阶:自定义数据集格式与训练参数优化

ChatGLM-finetune-LoRA进阶:自定义数据集格式与训练参数优化

ChatGLM-finetune-LoRA进阶:自定义数据集格式与训练参数优化 【免费下载链接】ChatGLM-finetune-LoRA 项目地址: https://gitcode.com/gh_mirrors/ch/ChatGLM-finetune-LoRA ChatGLM-finetune-LoRA是一款强大的工具,可帮助用户对ChatGLM模型进行…

2026/7/21 15:59:40阅读更多 →
从普通用户到域管:Pentestly完整攻击链构建与实战案例分析

从普通用户到域管:Pentestly完整攻击链构建与实战案例分析

从普通用户到域管:Pentestly完整攻击链构建与实战案例分析 【免费下载链接】pentestly Python and Powershell internal penetration testing framework 项目地址: https://gitcode.com/gh_mirrors/pe/pentestly 在企业内网渗透测试中,如何高效利…

2026/7/21 15:59:40阅读更多 →
Django-telegram-bot 后台任务处理:Celery + Redis 异步任务最佳实践

Django-telegram-bot 后台任务处理:Celery + Redis 异步任务最佳实践

Django-telegram-bot 后台任务处理:Celery Redis 异步任务最佳实践 【免费下载链接】django-telegram-bot My sexy Django python-telegram-bot Celery Redis Postgres Dokku GitHub Actions template 项目地址: https://gitcode.com/gh_mirrors/dja/djang…

2026/7/21 21:23:34阅读更多 →
Cresset自定义扩展:如何添加新的依赖和服务配置

Cresset自定义扩展:如何添加新的依赖和服务配置

Cresset自定义扩展:如何添加新的依赖和服务配置 【免费下载链接】cresset Template repository to build PyTorch projects from source on any version of PyTorch/CUDA/cuDNN. 项目地址: https://gitcode.com/gh_mirrors/cr/cresset Cresset是一个强大的Py…

2026/7/21 21:23:34阅读更多 →
如何使用Docker快速部署Superdesk:适合中小媒体的零成本方案

如何使用Docker快速部署Superdesk:适合中小媒体的零成本方案

如何使用Docker快速部署Superdesk:适合中小媒体的零成本方案 【免费下载链接】superdesk Superdesk is an end-to-end news creation, production, curation, distribution, and publishing platform. 项目地址: https://gitcode.com/gh_mirrors/su/superdesk …

2026/7/21 21:23:34阅读更多 →
鸿蒙 ArkTS 实战:Community Haircut Booking 从社区理发预约到生活服务工具完整解析

鸿蒙 ArkTS 实战:Community Haircut Booking 从社区理发预约到生活服务工具完整解析

鸿蒙 ArkTS 实战:Community Haircut Booking 从社区理发预约到生活服务工具完整解析 前言 Community Haircut Booking 是一个基于鸿蒙 ArkTS 与 ArkUI 声明式 UI 实现的生活服务类单页应用,核心场景是 社区理发师傅排班预约。 它把 维护当前师傅、提醒…

2026/7/21 21:23:34阅读更多 →
鸿蒙 ArkTS 实战:Home Cleaning Booking 从上门保洁预约到生活服务工具完整解析

鸿蒙 ArkTS 实战:Home Cleaning Booking 从上门保洁预约到生活服务工具完整解析

鸿蒙 ArkTS 实战:Home Cleaning Booking 从上门保洁预约到生活服务工具完整解析 前言 Home Cleaning Booking 是一个基于鸿蒙 ArkTS 与 ArkUI 声明式 UI 实现的生活服务类单页应用,核心场景是 上门保洁服务排期。 它把 维护服务项目、预约时段、地址备…

2026/7/21 21:23:34阅读更多 →
nest-winston:如何在Nest.js中集成Winston日志系统的完整指南

nest-winston:如何在Nest.js中集成Winston日志系统的完整指南

nest-winston:如何在Nest.js中集成Winston日志系统的完整指南 【免费下载链接】nest-winston A Nest module wrapper form winston logger 项目地址: https://gitcode.com/gh_mirrors/ne/nest-winston nest-winston是一个专为Nest.js框架设计的Winston日志系…

2026/7/21 21:21:25阅读更多 →
Go语言静态资源打包方案对比与实践指南

Go语言静态资源打包方案对比与实践指南

1. 项目背景与核心需求在Go语言开发中,我们经常需要处理静态资源文件的打包问题。无论是Web应用的模板文件、前端资源,还是配置文件、证书等,都需要随程序一起分发。传统做法是将这些文件与编译后的二进制文件放在同一目录下,但这…

2026/7/21 0:51:49阅读更多 →
Go语言实现高性能LDAP认证服务的架构与实践

Go语言实现高性能LDAP认证服务的架构与实践

1. 项目背景与核心价值LDAP(轻量级目录访问协议)作为企业级身份认证的黄金标准,已经服务了超过80%的财富500强公司。我在金融科技领域实施统一认证体系时,发现传统Java方案存在启动慢、内存占用高等痛点。而Go语言凭借其协程并发模…

2026/7/21 0:51:49阅读更多 →
【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

更多请点击: https://intelliparadigm.com 第一章:AI面试官实战指南的核心价值与适用场景 AI面试官并非替代人类HR的“黑箱工具”,而是以可解释、可审计、可迭代的方式,赋能招聘全链路的关键基础设施。其核心价值在于将主观经验沉…

2026/7/21 0:51:49阅读更多 →
Windows+macOS 通用 OpenClaw 部署流程,内置依赖一键启动智能桌面助手

Windows+macOS 通用 OpenClaw 部署流程,内置依赖一键启动智能桌面助手

📌教程适配:OpenClaw v2.7.9 | 兼容 Windows10/11、macOS 双系统 📖前言 当下各类本地 AI 工具层出不穷,多数产品仅能完成文字问答交互,很难直接操控电脑执行实际操作。OpenClaw,业内常称小龙虾 AI&#…

2026/7/21 0:01:46阅读更多 →
Codex 接入后 Bug 反增?复盘从个人演示到团队协作的“流程陷阱”

Codex 接入后 Bug 反增?复盘从个人演示到团队协作的“流程陷阱”

聊《一次Codex项目复盘,问题最后出在流程而不是模型》之前,先说一句实在的:别急着背概念,先看它在真实项目里到底解决什么问题。摘要先把这篇文章的目标说清楚:看完之后,你应该能判断这件事值不值得做&…

2026/7/21 0:01:46阅读更多 →
手把手搓一个五子棋游戏,零代码也能当“游戏开发者”

手把手搓一个五子棋游戏,零代码也能当“游戏开发者”

大家好,还是我。前几期带大家做了心情日记本和可视化大屏,后台有朋友留言:“能不能教点好玩的?我想做游戏,但一行代码都不会。”行,这期就安排。今天的目标:从零做一个五子棋游戏。 带AI对战、三…

2026/7/21 0:03:46阅读更多 →
YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

如果你在部署 YOLOv8 时,发现推理速度只有可怜的 1-2 FPS,而别人的演示视频却能跑到 30 FPS 以上,那么问题很可能不在模型本身,而在于你的整个处理链路。很多开发者拿到一个训练好的 YOLOv8 模型后,会直接使用官方示例…

2026/7/20 22:51:39阅读更多 →
Coze与Dify对比指南:低代码AI应用开发从入门到实战

Coze与Dify对比指南:低代码AI应用开发从入门到实战

1. 从零到一:为什么你需要了解 Coze 和 Dify?如果你对 AI 应用开发感兴趣,但一看到“大模型”、“智能体”、“工作流”这些词就头疼,觉得门槛太高,那这篇文章就是为你准备的。很多开发者,包括我自己&#…

2026/7/21 18:53:30阅读更多 →
AI生图工具怎么选?2026年6月版实测对比

AI生图工具怎么选?2026年6月版实测对比

做自媒体的朋友应该都有体会:配图一直是个让人头疼的问题。2026年,AI生图工具已经非常成熟了,但工具太多反而不知道怎么选。以下是截至2026年6月我对主流AI生图工具的实测对比。Midjourney V8.1:速度之王2026年6月11日&#xff0c…

2026/7/21 18:53:30阅读更多 →