QT模型/视图:自定义代理类型

简介

在模型/视图结构中,代理的作用就是在视图组件进入编辑状态编辑某个项时,提供一个临时的编辑器用于数据编辑,编辑完成后再把数据提交给数据模型。例如,在 QTableView 组件上双击一个单元格时,代理会提供一个临时的编辑器,默认是 QLineEdit 编辑框,在这个编辑框里修改项 的文字,按 Enter 键或焦点移动到其他单元格时完成编辑,编辑框内的文字会保存到数据模型。

自定义代理类需要从 QStyledItemDelegate 类继承,创建自定义代理类的实 例后,再将其设置为整个视图组件或视图组件的某行或某列的代理,以替代默认代理的功能。

QAbstractItemView 类定义了设置自定义代理的 3 个函数,分别是整个视图组件的代理、为某一列设置自定义代理、为某一行设置自定义代理,函数定义如下:

void setItemDelegate(QAbstractItemDelegate *delegate)

void setItemDelegateForColumn(int column, QAbstractItemDelegate *delegate)

void setItemDelegateForRow(int row, QAbstractItemDelegate *delegate)

QStyledItemDelegate 是视图组件使用的默认代理类,一般使用 QStyledItemDelegate 作为自定

义代理类的父类。要自定义一个代理类,必须重新实现 QStyledItemDelegate 中定义的 4 个虚函数。 这 4 个函数是由模型/视图系统自动调用的。

1.函数 createEditor()

函数 createEditor()可创建用于编辑模型数据的界面组件,称为代理编辑器,例如 QSpinBox

组件,或 QComboBox 组件。其函数原型定义如下:

QWidget *QStyledItemDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index)

其中,parent 是要创建的组件的父组件,一般就是窗口对象;option 是项的一些显示选项,是

QStyleOptionViewItem 类型的,包含字体、对齐方式、背景色等属性;index 是项在数据模型中的

模型索引,通过 index->model()可以获取项所属数据模型的对象指针。

2.函数 setEditorData()

函数 setEditorData()的功能是从数据模型获取项的某个角色(一般是 EditRole 角色)的数据, 然后将其设置为代理编辑器上显示的数据。其函数原型定义如下:

void QStyledItemDelegate::setEditorData(QWidget *editor, const QModelIndex &index)

参数 editor 就是前面用函数 createEditor()创建的代理编辑器,通过 index->model()可以获取项所属数据模型的对象指针,从而获取项的数据,然后将其显示在代理编辑器上。

3.函数 setModelData()

完成对当前单元格的编辑,例如输入焦点移到其他单元格时,系统会自动调用函数 setModelData(),

其功能是将代理编辑器里的输入数据保存到数据模型的项里。其函数原型定义如下:

void QStyledItemDelegate::setModelData(QWidget *editor, QAbstractItemModel *model,

const QModelIndex &index)

其中,editor 是代理编辑器,model 是数据模型,index 是所编辑的项在模型中的模型索引。

4.函数 updateEditorGeometry()

视图组件在界面上显示代理编辑器时,需要调用 updateEditorGeometry()函数为组件设置合适 的大小,例如在一个单元格里显示一个 QSpinBox 代理编辑器时,一般将其设置为单元格的大小。

其函数原型定义如下:

void QStyledItemDelegate::updateEditorGeometry(QWidget *editor,

const QStyleOptionViewItem &option, const QModelIndex &index)

其中,变量 option->rect 是 QRect 类型,表示代理编辑器的建议大小。一般将代理编辑器大小设 置为建议大小即可,即用下面的一行代码:

editor->setGeometry(option.rect);

案例:自定义代理类TFloatSpinDelegate

在QT Creator中新建C++类,并设置基类为 QStyledItemDelegate,要勾选 Add Q_OBJECT 复选框,因为要在 TFloatSpinDelegate 类中插入 Q_OBJECT 宏。

然后实现基类中的虚函数即可。

QWidget *TFloatSpinDelegate::createEditor(QWidget *parent,const QStyleOptionViewItem &option, const QModelIndex &index) const
{Q_UNUSED(option);Q_UNUSED(index);QDoubleSpinBox *editor = new QDoubleSpinBox(parent);editor->setFrame(false);editor->setMinimum(0);editor->setMaximum(20000);editor->setDecimals(2);     //显示两位小数return editor;
}void TFloatSpinDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
{float value = index.model()->data(index, Qt::EditRole).toFloat();QDoubleSpinBox *spinBox = static_cast<QDoubleSpinBox*>(editor);spinBox->setValue(value);
}void TFloatSpinDelegate::setModelData(QWidget *editor,QAbstractItemModel *model, const QModelIndex &index) const
{QDoubleSpinBox *spinBox = static_cast<QDoubleSpinBox*>(editor);//    spinBox->interpretText();float value = spinBox->value();QString str=QString::asprintf("%.2f",value);model->setData(index, str, Qt::EditRole);   //保存到数据模型
}void TFloatSpinDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option,const QModelIndex &index) const
{Q_UNUSED(index);editor->setGeometry(option.rect);
}

案例:自定义代理类TComboBoxDelegate

同样创建一个新的C++类,并实现基类的4个虚函数

void TComboBoxDelegate::setItems(QStringList items, bool editable)
{m_itemList=items;m_editable=editable;
}QWidget *TComboBoxDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option,const QModelIndex &index) const
{Q_UNUSED(option);Q_UNUSED(index);QComboBox *editor = new QComboBox(parent);        //自定义的组件editor->setEditable(m_editable);	//是否可编辑for (int i=0;i<m_itemList.count();i++)   //从字符串列表初始下拉列表editor->addItem(m_itemList.at(i));return editor;
}void TComboBoxDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
{QString str = index.model()->data(index, Qt::EditRole).toString();QComboBox *comboBox = static_cast<QComboBox*>(editor);comboBox->setCurrentText(str);
}void TComboBoxDelegate::setModelData(QWidget *editor, QAbstractItemModel *model,const QModelIndex &index) const
{QComboBox *comboBox = static_cast<QComboBox*>(editor);QString str = comboBox->currentText();model->setData(index, str, Qt::EditRole);
}void TComboBoxDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option,const QModelIndex &index) const
{Q_UNUSED(index);editor->setGeometry(option.rect);
}

自定义函数 setItems()用于设置变量 m_itemList 和 m_editable 的值,在函数 createEditor()里动态

创建 QComboBox 组件时,用于设置下拉列表的内容以及是否可以编辑。

使用自定义代理

m_model = new QStandardItemModel(2,FixedColumnCount,this); //创建数据模型m_selection = new QItemSelectionModel(m_model, this);           //创建选择模型//为tableView设置数据模型ui->tableView->setModel(m_model);  //设置数据模型ui->tableView->setSelectionModel(m_selection); //设置选择模型ui->tableView->setSelectionMode(QAbstractItemView::ExtendedSelection);ui->tableView->setSelectionBehavior(QAbstractItemView::SelectItems);///注意设置的这些代理组件只有在编辑时才有效果intSpinDelegate= new TSpinBoxDelegate(this);      ///setItemDelegate是整个视图组件的代理ui->tableView->setItemDelegateForColumn(0, intSpinDelegate);    //测深   setItemDelegateForColumn为某一列的代理floatSpinDelegate = new TFloatSpinDelegate(this);ui->tableView->setItemDelegateForColumn(1, floatSpinDelegate);  //垂深ui->tableView->setItemDelegateForColumn(2, floatSpinDelegate);  //方位ui->tableView->setItemDelegateForColumn(3, floatSpinDelegate);  //总位移comboDelegate = new TComboBoxDelegate(this);QStringList strList;strList<<"优"<<"良"<<"一般"<<"不合格";comboDelegate->setItems(strList,false);ui->tableView->setItemDelegateForColumn(4, comboDelegate);   //固井质量

这样增加了自定义代理功能后,在编辑“测深”列时,会在单元格的位置出现一个 SpinBox 用于输入整数;在编辑第二到四列的浮点数时,会出现一个 DoubleSpinBox 用于输入浮点数;在 编辑“固井质量”列时,会出现一个下拉列表框用于从下拉列表中选择一个字符串。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/62304.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ubuntu中使用ffmpeg库进行api调用开发

一般情况下&#xff0c;熟悉了ffmpeg的命令行操作&#xff0c;把他当成一个工具来进行编解码啥的问题不大&#xff0c;不过如果要把功能集成进自己的软件中&#xff0c;还是要调用ffmpeg的api才行。 ffmpeg的源码和外带的模块有点太多了&#xff0c;直接用官网别人编译好的库就…

实现 DataGridView 下拉列表功能(C# WinForms)

本文介绍如何在 WinForms 中使用 DataGridViewComboBoxColumn 实现下拉列表功能&#xff0c;并通过事件响应来处理用户的选择。以下是实现步骤和示例代码。 1. 效果展示 该程序的主要功能是展示如何在 DataGridView 中插入下拉列表&#xff0c;并在选择某一项时触发事件。 2.…

Docker Compose实战一( 轻松部署 Nginx)

通过过前面的文章&#xff08;Docker Compose基础语法&#xff09;你已经掌握基本语法和常用指令认识到Docker Compose作为一款强大工具的重要性&#xff0c;它极大地简化了多容器Docker应用程序的部署与管理流程。本文将详细介绍如何使用 Docker Compose 部署 Nginx&#xff0…

【免费】如何考取HarmonyOS应用开发者基础认证和高级认证(详细教程)

HarmonyOS应用开发者认证考试PC网址 基础&#xff1a;华为开发者学堂 高级&#xff1a;华为开发者学堂 注&#xff1a;免费认证&#xff0c;其中基础认证有免费的课程&#xff0c;浏览器用Edge。 (新题库有点懒&#xff0c;不更新了&#xff0c;点赞收藏后找我要新题库 2024…

瑞芯微开发板 烧写固件问题

自用rk3568-firefly-itx-3568q核心板fpga自研底板&#xff0c;因底板所需外设、功能与原厂有较大差异&#xff0c;故裁剪相应sdk&#xff0c;编译新的内核进行烧写。然而在更改设备树过程中kernel/drivers/media/i2c/fpga.c中的像素格式MEDIA_BUS_FMT_YUYV8_2X8误改成MEDIA_BUS…

photoblog解题过程

本题要求&#xff1a;通过sql注入&#xff0c;找到数据库中的账号密码&#xff0c;并成功登录。登录后利用文件上传&#xff0c;将一句话木马上传到数据库中&#xff0c;然后并对网站进行控制。 解题过程 1、通过在靶机中输入ifconfig&#xff0c;查到ip为192.168.80.153&…

QT获取tableview选中的行和列的值

查询数据库数据放入tableview&#xff08;tableView_database&#xff09;后 QSqlQueryModel* sql_model new QSqlQueryModel(this);sql_model->setQuery("select * from dxxxb_move_lot_tab");sql_model->setHeaderData(0, Qt::Horizontal, tr("id&quo…

「Mac玩转仓颉内测版46」小学奥数篇9 - 基础概率计算

本篇将通过 Python 和 Cangjie 双语实现基础概率的计算&#xff0c;帮助学生学习如何解决简单的概率问题&#xff0c;并培养逻辑推理和编程思维。 关键词 小学奥数Python Cangjie概率计算 一、题目描述 假设有一个袋子中有 5 个红球和 3 个蓝球&#xff0c;每次从袋子中随机…

Face2QR:可根据人脸图像生成二维码,还可以扫描,以后个人名片就这样用了!

今天给大家介绍的是一种专为生成个性化二维码而设计的新方法Face2QR&#xff0c;可以将美观、人脸识别和可扫描性完美地融合在一起。 下图展示为Face2QR 生成的面部图像&#xff08;第一行&#xff09;和二维码图像&#xff08;第二行&#xff09;。生成的二维码不仅忠实地保留…

电子商务人工智能指南 1/6 - 搜索、广告和发现

介绍 81% 的零售业高管表示&#xff0c; AI 至少在其组织中发挥了中等至完全的作用。然而&#xff0c;78% 的受访零售业高管表示&#xff0c;很难跟上不断发展的 AI 格局。 近年来&#xff0c;电子商务团队加快了适应新客户偏好和创造卓越数字购物体验的需求。采用 AI 不再是一…

nextcloud云盘的部署

借鉴链接&#xff1a;https://blog.csdn.net/guigenyi/article/details/126692747 创建自定义 Docker 网络 docker network create nextcloud-network 创建mysql的账号密码都是root 并将其连接到自定义网络 docker run --name mysql-container --network nextcloud-network -e…

图(dfs与bfs)算法1

开辟新专题&#xff01;不擅长的图它来了来了&#xff01;&#xff08;莫名激动 进度&#xff1a;10/100 另&#xff1a;没想到给自己挖了个坑&#xff0c;可以用dfs的基本上也可以用bfs&#xff0c;看来要双线并行了。 补&#xff1a;图算法是我近期得有30%的焦虑来源了&am…

一、测试工具LoadRunner Professional脚本编写-录制前设置

设置基于URL的脚本 原因:基于HTML的脚本会导致login接口不能正确录制 设置UTF-8 原因:不勾选此项会导致脚本中文变为乱码

Thonny IDE + MicroPython + ESP32 + GY-302 测量环境中的光照强度

GY-302是一款基于BH1750FVI光照强度传感器芯片的模块。该模块能够直接测量出环境中的光照强度&#xff0c;并将光照强度转换为数字信号输出。其具体参数如下表所示。 参数名称 参数特性 测量范围 0-65535 LX 测量精度 在环境光下误差小于20%&#xff0c;能够自动忽略50/60…

AJAX和XHR、fetch、axios的关系

AJAX中有两套原生的API&#xff0c;一个是XHR(XMLHttpRequest)&#xff0c;一个是Fetch API axios是第三方库&#xff0c;在浏览器环境中使用的是XHR umi-request也是第三方库&#xff0c;在浏览器环境中使用的是Fetch 在 AJAX&#xff08;Asynchronous JavaScript and XML&am…

openlayers地图缓存添加

//通过安装包localforage&#xff08;npm install localforage&#xff09;或https://cdnjs.cloudflare.com/ajax/libs/localforage/1.10.0/localforage.min.js tileCacheStore.js import localforage from localforage var tileCacheStorenull;// 从缓存中获取该瓦片 functio…

云轴科技ZStack出席中国电信国际EMCP平台香港发布会,持续推动海外合作

近日&#xff0c;以“云聚未来 翼起新篇”为主题的中国电信国际多云服务一站式平台&#xff08;E-surfing Managed Cloud Platform&#xff0c;简称EMCP平台&#xff09;新闻发布会在香港成功举办&#xff0c;标志着中国电信国际在云计算服务领域取得了又一重大进展。云轴科技…

2024.11.29——[HCTF 2018]WarmUp 1

拿到题&#xff0c;发现是一张图&#xff0c;查看源代码发现了被注释掉的提示 <!-- source.php--> step 1 在url传参看看这个文件&#xff0c;发现了这道题的源码 step 2 开始审计代码&#xff0c;分析关键函数 //mb_strpos($haystack,$needle,$offset,$encoding):int|…

brpc的二次封装以及brpc与etcd的联合

目的&#xff1a; 搭配etcd的注册中心管理能知道谁能提供什么服务&#xff0c;并用rpc进行服务调用 封装思想&#xff1a; 信道管理&#xff0c;将不同服务主机的通信信道管理起来 封装&#xff1a; 1.指定的信道管理类 一个服务通常会有多个节点&#xff0c;每个节点都会…

【提升效率】如何写好一份详细设计文档

版本日期修订人描述V1.02024/12/6nick huang创建文档 背景 CSDN在发起“如何做好一份技术文档”的活动。 想起我最近在写一份详细设计&#xff0c;有一些感受&#xff1a; 一份考虑较周全的“详细设计文档模板”能起到质量保底的作用。 当一名初级技术人员需要编写详细设计文…