Qt Model/View之代理

概念

与模型-视图-控制器模式不同,模型/视图设计没有包含一个完全独立的组件来管理与用户的交互。通常,视图负责向用户展示模型数据,并负责处理用户输入。为了在获取输入的方式上具有一定的灵活性,交互由委托执行。这些组件提供输入功能,还负责在某些视图中渲染单个项目。控制委托的标准接口定义在QAbstractItemDelegate类中。

委托希望能够通过实现paint()和sizeHint()函数来渲染它们自己的内容。然而,简单的基于部件的委托可以继承QStyledItemDelegate而不是QAbstractItemDelegate,并利用这些函数的默认实现。

委托编辑器可以通过使用小部件来管理编辑过程,也可以通过直接处理事件来实现。第一种方法将在本节后面介绍,它也会在Spin Box委托的例子中展示。

Pixelator的例子展示了如何创建一个自定义委托来为tableview执行特殊的渲染。

使用现有委托

Qt提供的标准视图使用QStyledItemDelegate实例来提供编辑功能。delegate接口的默认实现会以标准视图(QListView、QTableView和QTreeView)的通常风格渲染元素。

所有标准角色都由标准视图使用的默认委托处理。解释它们的方式在QStyledItemDelegate文档中有描述。

视图使用的委托由itemDelegate()函数返回。setItemDelegate()函数允许你为标准视图安装一个自定义委托,在为自定义视图设置委托时,必须使用这个函数。

一个简单的委托

这里实现的委托使用QSpinBox来提供编辑功能,主要用于显示整数的模型。虽然我们为此设置了一个自定义的基于整数的表模型,但我们可以轻松地使用QStandardItemModel,因为自定义委托控制数据输入。我们构建一个表视图来显示模型的内容,这将使用自定义委托进行编辑。

我们从QStyledItemDelegate继承委托的子类,因为我们不想编写自定义显示函数。但是,我们仍然必须提供管理编辑器小部件的函数:

class SpinBoxDelegate : public QStyledItemDelegate
{Q_OBJECTpublic:SpinBoxDelegate(QObject *parent = nullptr);QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option,const QModelIndex &index) const override;void setEditorData(QWidget *editor, const QModelIndex &index) const override;void setModelData(QWidget *editor, QAbstractItemModel *model,const QModelIndex &index) const override;void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option,const QModelIndex &index) const override;
};

注意,构造委托时没有设置编辑器部件。我们只在需要时构建编辑器部件。

提供编辑器

在这个例子中,当表视图需要提供一个编辑器时,它要求委托提供一个适合于正在修改的项的编辑器部件。createEditor()函数提供了委托设置适当部件所需的一切:

QWidget *SpinBoxDelegate::createEditor(QWidget *parent,const QStyleOptionViewItem &/* option */,const QModelIndex &/* index */) const
{QSpinBox *editor = new QSpinBox(parent);editor->setFrame(false);editor->setMinimum(0);editor->setMaximum(100);return editor;
}

请注意,我们不需要保留指向编辑器部件的指针,因为当不再需要它时,视图会负责销毁它。

我们在编辑器上安装了委托的默认事件过滤器,以确保它提供了用户期望的标准编辑快捷方式。可以向编辑器添加额外的快捷方式,以允许更复杂的行为;这些将在编辑提示一节中讨论。

视图通过调用我们后面为这些目的定义的函数来确保编辑器的数据和几何信息被正确设置。我们可以根据视图提供的模型索引创建不同的编辑器。例如,如果我们有一列整数和一列字符串,我们可以返回QSpinBox或QLineEdit,这取决于正在编辑哪一列。

委托必须提供将模型数据复制到编辑器中的函数。在这个例子中,我们读取了存储在display角色中的数据,并相应地设置了spin box中的值。(设置编辑器的值

void SpinBoxDelegate::setEditorData(QWidget *editor,const QModelIndex &index) const
{int value = index.model()->data(index, Qt::EditRole).toInt();QSpinBox *spinBox = static_cast<QSpinBox*>(editor);spinBox->setValue(value);
}

在这个例子中,我们知道编辑器小部件是一个spin box,但我们可以为模型中的不同类型的数据提供不同的编辑器,在这种情况下,我们需要在访问其成员函数之前将小部件转换为适当的类型。

向模型提交数据

当用户完成微调框中的值编辑后,视图会调用setModelData()函数,要求委托将编辑后的值存储到模型中。

void SpinBoxDelegate::setModelData(QWidget *editor, QAbstractItemModel *model,const QModelIndex &index) const
{QSpinBox *spinBox = static_cast<QSpinBox*>(editor);spinBox->interpretText();int value = spinBox->value();model->setData(index, value, Qt::EditRole);
}

由于视图为委托管理编辑器部件,我们只需要使用提供的编辑器内容更新模型。在本例中,我们确保微调框是最新的,并使用指定的索引用它包含的值更新模型。

标准的QStyledItemDelegate类通过发出closeEditor()信号来通知视图何时完成编辑。视图确保编辑器部件被关闭和销毁。在这个例子中,我们只提供了简单的编辑功能,所以我们永远不需要发射这个信号。

所有对数据的操作都通过QAbstractItemModel提供的接口来执行。这使得委托基本上独立于它所操作的数据类型,但是为了使用某些类型的编辑器部件,必须做一些假设。在这个例子中,我们假设模型总是包含整数值,但我们仍然可以将此委托用于不同类型的模型,因为QVariant为意外数据提供了合理的默认值。

更新编辑器的几何形状

委托的职责是管理编辑器的几何图形。几何形状必须在编辑器创建时设置,并且当项目的大小或在视图中的位置发生变化时设置。幸运的是,该视图在视图选项对象中提供了所有必要的几何信息。

void SpinBoxDelegate::updateEditorGeometry(QWidget *editor,const QStyleOptionViewItem &option,const QModelIndex &/* index */) const
{editor->setGeometry(option.rect);
}

在这个例子中,我们只使用项目矩形中的view选项提供的几何信息。呈现具有多个元素的项的委托不会直接使用项矩形。它将使编辑器相对于项目中的其他元素进行定位。

编辑提示

在编辑之后,委托应该向其他组件提供有关编辑过程结果的提示,并提供有助于任何后续编辑操作的提示。这是通过发送带有适当提示的closeEditor()信号来实现的。这是由默认的QStyledItemDelegate事件过滤器处理的,我们在构建spin box时安装了它。

可以调整spin box的行为,使其对用户更友好。在QStyledItemDelegate提供的默认事件过滤器中,如果用户点击Return来确认他们在微调框中的选择,则委托将值提交给模型并关闭微调框。我们可以通过在微调框上安装自己的事件过滤器来改变这种行为,并根据需要提供编辑提示;例如,我们可以发送带有EditNextItem提示的closeEditor(),以自动开始编辑视图中的下一项。

另一种不需要使用事件过滤器的方法是提供我们自己的编辑器部件,为了方便,可能会子类化QSpinBox。这种替代方法将使我们能够更多地控制编辑器部件的行为,但代价是编写额外的代码。如果需要自定义标准Qt编辑器部件的行为,在委托中安装事件过滤器通常更容易。

委托不必发出这些提示,但是那些不发出提示的委托与应用程序的集成程度较低,而且与那些发出提示以支持常见编辑操作的委托相比,它们的可用性较差。

Model/View Programming | Qt Widgets 5.15.17

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

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

C++---内存管理

1 C/C内存分布 栈区&#xff1a;由编译器自动分配和释放&#xff0c;存放运行时候的局部变量&#xff0c;函数参数&#xff0c;返回数据&#xff0c;返回地址。 堆区&#xff1a;一般由程序员自己分配&#xff0c;然后自己释放&#xff0c;例如栈的实现malloc开辟的数组空间。…

中秋假期用向日葵,临时工作需求远程控制随时解决

不知你是否在这美好时刻赏月看灯&#xff1f;有没有收到公司发的月饼呢&#xff1f; 在如今这个讲究降本增效的时代&#xff0c;仪式感早已变得稀少。公司发的月饼还没拆开&#xff0c;新消息就已弹出在公司群里。 此刻心里仿佛有万马奔腾&#xff0c;但很快又如湖水般平静&am…

拒绝千篇一律,AI帮你定制独一无二的个人写真

每个女人都渴望展现最美的自己&#xff0c;你是否厌倦了拍出千篇一律的照片&#xff1f;今天&#xff0c;我要告诉你一个秘密&#xff0c;用简单三步&#xff0c;即可打造属于你的独一无二个人写真&#xff01;文生图、蒙版换脸、图生图&#xff0c;三步化身超级模特&#xff0…

基于TRIZ的救援机器人轻量化设计

在救援机器人设计中&#xff0c;轻量化是一个至关重要的目标&#xff0c;它直接关系到机器人的便携性、运输效率以及在复杂环境中的作业能力。TRIZ理论为我们提供了一套系统化的工具和方法&#xff0c;用于解决设计过程中遇到的各种挑战&#xff0c;特别是在实现轻量化目标时&a…

初识爬虫4

1.理解代理ip&#xff0c;正向代理和反向代理 2.代理ip分类&#xff0c;根据匿名度分类&#xff1a;透明&#xff0c;匿名&#xff0c;高匿 3.防止频繁向同一个域名发送请求被封ip,需使用代理ip # -*- coding: utf-8 -*- import requestsurl https://www.baidu.comproxies {…

从关键新闻和最新技术看AI行业发展(第三十一期2024.8.26-9.8) |【WeThinkIn老实人报】

写在前面 【WeThinkIn老实人报】旨在挖掘AI行业的关键新闻和最新技术&#xff0c;同时Rocky会对其中的关键信息进行解读&#xff0c;力求让读者们能从容掌握AI科技潮流。 欢迎大家关注Rocky的公众号&#xff1a;WeThinkIn 欢迎大家关注Rocky的知乎&#xff1a;Rocky Ding AIGC算…

微型导轨加工环境需避免的隐患!

微型导轨是一种小巧精密的线性定位解决方案&#xff0c;其高速度、低噪音的特点使得它在现代制造业中扮演着越来越重要的角色。而微型导轨对于加工环境的要求主要体现在以下几个方面&#xff1a; 1、温度控制&#xff1a;加工环境需要保持在适宜的温度范围内&#xff0c;过高或…

一分钟教你 全平台隔空投送文件 LoaclSend保姆级教程

主要内容 什么是LoaclSend 详细步骤 1.下载LoaclSend 2.使用MoleSDN 异地访问 3.一切就绪&#xff0c;打开LocalSend 发送文件 什么是LoaclSend 一款开源的文件传输工具&#xff0c;旨在提供简单、安全、快速的本地文件传输。 LocalSend可以免费使用且无需注册登录&…

音视频直播应用场景探讨之RTMP推流还是GB28181接入?

技术背景 好多开发者跟我们沟通音视频解决方案的时候&#xff0c;不清楚什么时候用RTMP推送模块&#xff0c;什么时候用GB28181设备接入模块&#xff0c;也不清楚二者差异化。实际上&#xff0c;RTMP推流和GB28181接入模块&#xff0c;在很多方面存在差异&#xff0c;如应用领…

个人学习笔记7-5:动手学深度学习pytorch版-李沐

#人工智能# #深度学习# #语义分割# #计算机视觉# #神经网络# 计算机视觉 13.10 转置卷积 例如&#xff0c;卷积层和汇聚层&#xff0c;通常会减少下采样输入图像的空间维度&#xff08;高和宽&#xff09;。然而如果输入和输出图像的空间维度相同&#xff0c;在以像素级分类…

【MPC】无人机模型预测控制复现Data-Driven MPC for Quadrotors项目(Part 1)

无人机模型预测控制复现Data-Driven MPC for Quadrotors项目 参考链接背景和问题方法与贡献实验结果安装ROS创建工作空间下载RotorS仿真器源码和依赖创建Python虚拟环境下载data_driven_mpc仓库代码下载并配置ACADO求解器下载并配置ACADO求解器的Python接口下载并配置rpg_quadr…

智能智造和工业软件研发平台SCSAI功能介绍

用爱编程30年&#xff0c;倾心打造工业和智能智造软件研发平台SCIOT,用创新的方案、大幅的让利和极致的营销&#xff0c;致力于为10000家的中小企业实现数字化转型&#xff0c;打造数字化企业和智能工厂&#xff0c;点击上边蓝色字体&#xff0c;关注“AI智造AI编程”或文末扫码…

union和union all的区别,别再傻傻分不清楚了!

union和union all的区别 一、 显示结果不同二、对重复结果的处理不同三、对排序的处理不同四、测试验证1.创建user表并插入测试数据2.通过union关联查询&#xff0c;发现结果自动去重3.通过union all关联查询&#xff0c;发现结果查询所有&#xff0c;并未去重 一、 显示结果不…

记录开发一个英语听力训练网站

背景 在当前全球经济衰退的背景下&#xff0c;IT相关的工作在国内的竞争也是越来越激烈&#xff0c;为了能够获得更多的可能性&#xff0c;英语的学习也许能为程序员打开一扇新的窗户&#xff0c;比如很多远程的工作尤其是国际化背景的工作团队&#xff0c;英语的协作沟通是必…

pdf怎么加页码?5种pdf添加页码指南分享,快来领取!

如何在一个包含大量页面的大型pdf文件中快速找到特定的页面或信息呢&#xff1f;最简便的方法就是为pdf添加页码。pdf添加页码能够清晰显示页面顺序&#xff0c;帮助读者轻松浏览大型pdf文档&#xff0c;同时也便于寻找特定章节和确定整体长度。然而&#xff0c;并非所有pdf文件…

【LeetCode】每日一题 2024_9_14 从字符串中移除星号(模拟)

前言 每天和你一起刷 LeetCode 每日一题~ LeetCode 启动&#xff01; 今天的题目曾经的我做过了 . . . 又是复习的一天 题目&#xff1a;从字符串中移除星号 代码与解题思路 func removeStars(s string) string {// 本题的核心&#xff1a;生成的输入保证总是可以执行题面中…

【大数据】MapReduce的“内存增强版”——Spark

【大数据】MapReduce的“内存增强版”——Spark 文章脉络 Spark架构 Spark-core SparkConf 和 SparkContext RDD Spark集群 Spark-sql 在大数据时代&#xff0c;数据处理和分析成为企业竞争的重要手段。Hadoop作为大数据处理的基石&#xff0c;其核心组件MapReduce在众多…

完结马哥教育SRE课程--就业篇

文章目录 一、Linux基础入门1.Linux基本架构2.什么是shell3.执行命令4.Shell中的两类命令5.常见命令6.输出信息echo7.tab键补全8.获取帮助 二、文件管理和IO重定向1.文件系统目录结构2.文件系统目录功能3.linux下的文件类型4.文件操作命令5.文件状态stat6.确定文件内容7.文件通…

如何搭建一个自己的外卖会员卡系统?

大家好&#xff0c;我是鲸天科技千千&#xff0c;大家都知道我是做小程序开发的&#xff0c;平时会给大家分享一些互联网相关的创业项目&#xff0c;感兴趣的可以跟我关注一下。 搭建一个首先就是要搭建一个自己的返利小程序也就是外卖会员卡小程序&#xff0c;然后客户在我们…

锁表导致系统挂了,谨慎DDL操作

作者&#xff1a;IT邦德 中国DBA联盟(ACDU)成员&#xff0c;10余年DBA工作经验&#xff0c; Oracle、PostgreSQL ACE CSDN博客专家及B站知名UP主&#xff0c;全网粉丝10万 擅长主流Oracle、MySQL、PG、 高斯及Greenplum备份恢复&#xff0c; 安装迁移&#xff0c;性能优化、故障…