Qt 模型视图(四):代理类QAbstractItemDelegate

news2024/9/20 20:18:47

文章目录

  • Qt 模型视图(四):代理类`QAbstractItemDelegate`
    • 1.基本概念
      • 1.1.使用现有代理
      • 1.2.一个简单的代理
    • 2.提供编辑器
    • 3.向模型提交数据
    • 4.更新编辑器的几何图形
    • 5.编辑提示

Qt 模型视图(四):代理类QAbstractItemDelegate

模型/视图结构是一种将数据存储界面展示分离的编程方法。模型存储数据,视图组件显示模型中的数据,在视图组件里修改的数据会被自动保存到模型里。模型的数据来源可以是内存中的字符串列表或二维表格型数据,也可以是数据库中的数据表,一种模型可以用不同的视图组件来显示数据,所以模型/视图结构是一种高效、灵活的编程结构。

1.基本概念

与模型-视图-控制器模式不同,模型/视图设计不包括一个完全独立的组件来管理与用户的交互。通常,视图负责向用户呈现模型数据,并处理用户输入。为了使获得此输入的方式具有一定的灵活性,交互由代表执行。这些组件提供输入功能,还负责在某些视图中呈现单个项目。控制委托的标准接口在QAbstractItemDelegate类中定义。
委托应该能够通过实现paint()和sizeInt()函数来呈现自己的内容。但是简单的基于小部件的委托可以子类化QStyleItemDelegate替代QAbstractItemDelegate,并利用这些函数的默认实现。
代理的编辑器可以通过使用小部件来管理编辑过程或直接处理事件来实现。稍后将介绍第一种方法。

1.1.使用现有代理

Qt提供的标准视图使用QStyleItemDelegate的实例来提供编辑功能。委托接口的此默认实现以每个标准视图的常用样式呈现项目:QListView、QTableView和QTreeView
所有标准角色都由标准视图使用的默认委托处理。QStyledItemDelegate文档中描述了这些内容的解释方式。
视图使用的委托由itemDelegate()函数返回。setItemDelegate()函数允许您为标准视图安装自定义委托,在为自定义视图设置委托时必须使用此函数。

1.2.一个简单的代理

这里实现的委托使用QSpinBox提供编辑功能,主要用于显示整数的模型。尽管我们为此目的设置了一个基于整数的自定义表模型,但我们本可以很容易地使用QStandardItemModel,因为自定义委托控制着数据输入。我们构造了一个表视图来显示模型的内容,这将使用自定义委托进行编辑。
在这里插入图片描述
我们将委托从QStyleItemDelegate子类化,因为我们不想编写自定义显示函数。但是,我们仍然必须提供管理编辑器小部件的功能:

 class SpinBoxDelegate : public QStyledItemDelegate
 {
     Q_OBJECT
 public:
     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;
 };

 SpinBoxDelegate::SpinBoxDelegate(QObject *parent)
     : QStyledItemDelegate(parent)
 {
 }

请注意,在构造委托时不会设置编辑器小部件。我们只在需要时构建编辑器小部件。

2.提供编辑器

在这个例子中,当表视图需要提供编辑器时,它会要求委托提供一个适合被修改项目的编辑器小部件。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,具体取决于正在编辑的列。
委托必须提供将模型数据复制到编辑器中的函数。在这个例子中,我们读取存储在显示角色中的数据,并相应地在旋转框中设置值。

 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);
 }

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

3.向模型提交数据

当用户在数字设定框中编辑完值后,视图会调用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为意外数据提供了合理的默认值。

4.更新编辑器的几何图形

管理编辑器的几何图形是代理的责任。创建编辑器,更改项目在视图中的大小或位置时,必须设置几何图形。幸运的是,视图在视图选项对象中提供了所有必要的几何信息。

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

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

5.编辑提示

编辑后,代理应向其他组件提供有关编辑过程结果的提示,并提供有助于任何后续编辑操作的提示。这是通过发出带有适当提示的closeEditor()信号来实现的。这是由构建spin box时安装的默认QStyledItemDelegate事件过滤器来处理的。
可以调整数字设定框的行为,使其更便于用户使用。在QStyledItemDelegate提供的默认事件过滤器中,如果用户点击Return确认他们在数字设定框中的选择,则代理将值提交给模型并关闭数字设定框。我们可以通过在数字设定框上安装自己的事件过滤器来改变这种行为,并提供适合我们需求的编辑提示;例如,我们可能会发出带有EditNextItem提示的closeEditor(),以自动开始编辑视图中的下一个项目。
另一种不需要使用事件过滤器的方法是提供我们自己的编辑器小部件,为了方便起见,可能会对QSpinBox进行子类化。这种替代方法将使我们能够以编写额外代码为代价,更好地控制编辑器小部件的行为。如果需要自定义标准Qt编辑器小部件的行为,通常在委托中安装事件过滤器会更容易。
委托不必发出这些提示,但那些没有发出提示的委托将较少地集成到应用程序中,并且将比那些发出提示以支持常见编辑操作的委托更难使用。

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

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

相关文章

手写流程图元素检测系统源码分享

手写流程图元素检测检测系统源码分享 [一条龙教学YOLOV8标注好的数据集一键训练_70全套改进创新点发刊_Web前端展示] 1.研究背景与意义 项目参考AAAI Association for the Advancement of Artificial Intelligence 项目来源AACV Association for the Advancement of Comput…

安装WINDOWS微软商店已下架的WSL系统,以UBUNTU 16.04 为例

下载WSL系统 方法1&#xff1a;POWERSHELL 用powershell下载 PowerShell Invoke-WebRequest -Uri https://aka.ms/wsl-ubuntu-1604 -OutFile Ubuntu.appx -UseBasicParsing 1 如果下载时间很长&#xff0c;可以这样把进度条关闭&#xff1a; $ProgressPreference Silentl…

Vue特性

Vue概念 Soc原则&#xff1a;关注点分离原则 Vue 的核心库只关注视图层&#xff0c;方便与第三方库或既有项目整合 Model&#xff08;模型&#xff09;&#xff1a;表示应用程序的核心数据和业务逻辑。模型通常包含数据和与数据相关的操作。它独立于视图和视图模型&#xff…

Rust表达一下中秋祝福,群发问候!

一、Rust表达一下中秋祝福 在Rust中&#xff0c;表达中秋佳节的祝福可以通过定义一个包含祝福语的字符串变量&#xff0c;并使用标准输出函数来打印这个字符串。以下是一个简单的Rust程序示例&#xff0c;用于展示如何用Rust编写并打印中秋佳节的祝福语&#xff1a; fn main()…

3谐振功率放大器的实际电路设计

1原理电路 下图是谐振功率放大器的原理电路&#xff0c;如果我们照着下图搭一个电路&#xff0c;会发现它可能实现不了功率放大?这是为什么&#xff1f; 2实际电路设计 2.1要注意直流馈电线路 馈电原则(馈电供电)&#xff1a; 1&#xff09;保证直流电流分量流过直流电源&…

wordpress源码资源站整站打包32GB数据,含6.7W条资源数据

源码太大了&#xff0c;足足32gb&#xff0c;先分享给大家。新手建立资源站&#xff0c;直接用这个代码部署一下&#xff0c;数据就够用了。辅助简单做下seo&#xff0c;一个新站就OK了。 温馨提示&#xff1a;必须按照顺序安装 代码下载

【Linux】理解和解释shell命令的工具

&#x1f41a;作者简介&#xff1a;花神庙码农&#xff08;专注于Linux、WLAN、TCP/IP、Python等技术方向&#xff09;&#x1f433;博客主页&#xff1a;花神庙码农 &#xff0c;地址&#xff1a;https://blog.csdn.net/qxhgd&#x1f310;系列专栏&#xff1a;C语言编程&…

阿德里安·欧拉博士Dr Adrian Euler

阿德里安欧拉博士 金融学副教授 https://apps.dur.ac.uk/biography/image/777 屬属 联系商学院金融学副教授 传 杜伦大学商学院金融学副教授&#xff08;教学&#xff09;阿德里安欧拉博士是一位金融理论家和实践家&#xff0c;在行业和高等教育实践方面拥有丰富的经验 - 教学、…

工程师 - PCI介绍

What Is Peripheral Component Interconnect (PCI)? 什么是外设组件互连&#xff08;PCI&#xff09;&#xff1f; PCI bus connects peripherals to the motherboard PCI 总线将外设与主板连接起来 By Mark Casey Updated on October 17, 2021 Reviewed by Ryan Perian 外…

web网站的任意文件上传下载漏洞解析

免责申明 本文仅是用于学习检测自己搭建的任意文件上传下载漏洞相关原理,请勿用在非法途径上,若将其用于非法目的,所造成的一切后果由您自行承担,产生的一切风险和后果与笔者无关;本文开始前请认真详细学习《‌中华人民共和国网络安全法》‌及其所在国家地区相关法规内容【…

Python 的 WSGI 简单了解

从 flask 的 hello world 说起 直接讨论 WSGI&#xff0c;很多人可能没有概念&#xff0c;我们还是先从一个简单的 hello world 程序开始吧。 from flask import Flaskapp Flask(__name__)app.route("/", methods[GET]) def index():return "Hello world!&q…

完结马哥教育SRE课程--服务篇

文章目录 一、MySQL1.数据库范式2.SQL结构化查询语言3.存储引擎InnoDB和MyISAM4.索引Index5.事务6.日志管理7.MySQL备份和恢复8.MySQL主从复制9.MySQL高可用MHA 二、Redis1.NoSQL的特点2.Redis特性3.ROB和AOF4.Redis数据结构5.Redis主从复制6.Redis 哨兵机制7.Redis Cluster 三…

bpf的了解以及bpftrace的简单练习

最近接触到bpf的概念&#xff0c;简单做一些练习&#xff0c;做以下整理&#xff0c;学习笔记。 0&#xff1a;总结 使用ebpf可以实现的功能打开新世界&#xff0c;可以不改变源码的情况下&#xff0c;实现内存&#xff0c;网络&#xff0c;对应接口等各种期望内容的监控。 …

记忆化搜索(算法篇)

算法篇之记忆化搜索 记忆化搜索 概念&#xff1a; 记忆化搜索就是深度优先搜索的一种优化策略&#xff0c;记忆化搜索深度优先搜索形式动态规划思想由于dfs本质是暴力搜索&#xff0c;没有很好地处理重叠子问题&#xff0c;因此很低效记忆化算法在求解地时候还是按照自顶向下…

固态硬盘数据怎么恢复?用这4个软件你就知道了。

其实想要恢复固态硬盘里面的数据&#xff0c;方法有很多种。我们可以从回收站恢复&#xff0c;用备份恢复&#xff0c;或者是找专业人员帮助恢复。如果这些方法都不行的话&#xff0c;可以试试使用专业的数据恢复软件。我知道的数据恢复软件就有好几款&#xff0c;可以分享给大…

java编程行业特点

Java编程行业是一个庞大且充满活力的领域&#xff0c;它涵盖了从桌面应用到企业级应用、从Web开发到移动应用、从大数据处理到云计算服务的广泛范围。Java作为一种跨平台、面向对象的编程语言&#xff0c;自1995年发布以来&#xff0c;一直受到全球开发者的青睐&#xff0c;并在…

我的5周年创作纪念日,不忘初心,方得始终。

一、机缘 五年前&#xff0c;我怀着对知识的渴望和分享的热情&#xff0c;踏入了 CSDN 这个充满活力的技术交流平台&#xff0c;开启了我的创作之旅。那时的我&#xff0c;刚刚在技术的海洋中启航&#xff0c;渴望找到一个地方记录自己的成长足迹&#xff0c;与更多的人分享自…

【模板的特殊继承关系】用参数化的方式表达成员函数的虚拟性

一、使用混入技术实现的简单范例 成员函数的虚拟性可以通过特殊的继承来表达&#xff0c;我们先看看一个简单的范例&#xff0c;通过混入技术来实现&#xff1a; //基类 template<typename... T> class Base:public T... { public:void myfunc(){std::cout << &q…

禹神3小时快速上手typescript

一、TypeScript简介 TypeScript 由微软开发&#xff0c;是基于 JavaScript 的⼀个扩展语⾔。TypeScript 包含了 JavaScript 的所有内容&#xff0c;即&#xff1a; TypeScript 是 JavaScrip t 的超集。TypeScript 增加了&#xff1a;静态类型检查、接⼝、 泛型等很多现代开发特…

6--SpringBootWeb案例(详解)

目录 环境搭建 部门管理 查询部门 接口文档 代码 删除部门 接口文档 代码 新增部门 接口文档 代码 已有前端&#xff0c;根据接口文档完成后端功能的开发 成品如下&#xff1a; 环境搭建 1. 准备数据库表 (dept 、 emp) -- 部门管理 create table dept( id int un…