Qt 自定义代理类

一.使用步骤

  1. 继承QStyledItemDelegate类:首先创建一个新的类并继承自QStyledItemDelegate类,作为您的自定义代理类。

  2. 实现代理类的构造函数:在代理类中实现构造函数,并在构造函数中调用基类的构造函数,可以选择传入一个QObject类型的父对象。

  3. 重写需要定制的函数:根据您的需求,重写QStyledItemDelegate类中的需要进行定制的函数。常用的函数包括paint、sizeHint、createEditor等。根据您的需求决定需要重写哪些函数。

  4. 修改绘制逻辑(可选):在重写的paint函数中修改绘制逻辑,根据数据的类型或特定条件进行不同的绘制操作。例如,在上面的例子中,根据数据类型添加货币符号。

  5. 在视图中应用代理:将您自定义的代理类设置给视图部件的setItemDelegate()函数,这样视图中的数据显示就会按照您的定制进行展示。

  6. 调试和优化:在应用自定义代理后,可以进行调试和优化,确保显示效果符合预期。

二.具体实现 

1.继承QStyledItemDelegate类

class CurrencyDelegate : public QStyledItemDelegate
{
public:CurrencyDelegate(QObject *parent = nullptr) : QStyledItemDelegate(parent){}
};

问题1:CurrencyDelegate(QObject *parent = nullptr) : QStyledItemDelegate(parent)参入如何传递

在上面的例子中,通过CurrencyDelegate类的构造函数,将parent参数传递给QStyledItemDelegate的构造函数,从而在实例化CurrencyDelegate时,也对QStyledItemDelegate进行了初始化。这种方式可以确保自定义代理类和基类之间的关联,使得自定义代理类可以继承QStyledItemDelegate的属性和行为。

2.对代理类进行实现

对继承的父类的函数进行重写。

//创建代理编辑器
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;

示例如下:

/创建代理组件的时候,调用这个虚函数
QWidget *QIntSalaryDelagate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const
{//不使用参数Q_UNUSED(option);Q_UNUSED(index);QSpinBox*editor=new QSpinBox(parent);editor->setFrame(false);//无边框editor->setMinimum(2000);editor->setMaximum(100000);editor->setSingleStep(100);return editor;
}void QIntSalaryDelagate::setEditorData(QWidget *editor, const QModelIndex &index) const
{int value = index.model()->data(index).toInt();//数据模型中的数据QSpinBox*spinBox=static_cast<QSpinBox*>(editor);//这是上面创建的东西spinBox->setValue(value);}void QIntSalaryDelagate::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);}void QIntSalaryDelagate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const
{editor->setGeometry(option.rect);//就原来的位置
}

 代码解读:

int value = index.model()->data(index).toInt();

这段代码的作用是从数据模型中获取特定索引处的数据,并将其转换为整数类型。

  • index.model():通过QModelIndex对象的model()方法获取索引所属的数据模型。
  • data(index):通过数据模型的data()方法获取指定索引位置的数据。
  • toInt():将获取到的数据转换为整数类型。

因此,int value将存储从数据模型中获取的指定索引位置的数据,并转换为整数类型,以便在后续代码中使用。

问题: 代理就是对模型的数据进行二次加工,然后以另外一种方式放回到模型中吗

代理(Delegate)在模型视图编程中扮演着重要角色,用于对模型的数据进行二次加工或自定义呈现方式,使其能够以不同的方式呈现给视图控件(如表格、列表等)。代理常用于定制数据的展示形式、编辑方式或交互行为。

在您提供的代码中,QIntSalaryDelagate代理的setEditorData函数就是一个很好的例子。它通过获取模型中的数据并将其设置到编辑器小部件中,实现了以特定方式呈现数据给用户进行编辑的功能。编辑器中修改后的数据经过处理后可以再次存回到模型中。

因此,代理可用于数据的二次处理、自定义展示逻辑以及用户交互的控制,使模型能够以更灵活、符合需求的方式与视图进行交互。

三. static_cast<>介绍

static_cast<> 是 C++ 中的一种类型转换操作符,用于执行编译时的静态类型转换。它可以进行标准数据类型之间的转换(例如整数转换为浮点数)、基类指针或引用到派生类指针或引用的转换等。

QSpinBox* spinBox = static_cast<QSpinBox*>(editor);

 这行代码将 editor 作为 QWidget 类型的指针,转换为 QSpinBox 类型的指针。这种类型转换是在编译时进行的,因此需要开发者明确确认这两种类型之间存在继承或兼容关系,否则会造成编译错误。

 示例分析:

#include <iostream>class Base {
public:virtual void display() {std::cout << "Base class" << std::endl;}
};class Derived : public Base {
public:void display() override {std::cout << "Derived class" << std::endl;}
};int main() {Base baseObj;Derived derivedObj;Base* basePtr = &derivedObj;Derived* derivedPtr = static_cast<Derived*>(basePtr);derivedPtr->display(); // Output: "Derived class"return 0;
}

在上面的示例中,我们创建了一个基类 Base 和一个派生类 Derived。通过将 Derived 类对象的地址赋给 Base 类指针,我们可以使用 static_cast 将其转换回 Derived 类指针,并调用 Derived 类的成员函数。

需要注意的是,对于存在多态的情况(基类有虚函数,派生类重写了这些虚函数),最好使用 dynamic_cast 进行转换,因为 dynamic_cast 运行时执行类型检查,能够确定是否安全进行类型转换。

问题1:int value = index.model()->data(index).toInt();

这行代码是将当前选定项目的数据从模型中读取,并将其转换为整数型。具体来说,代码中的工作步骤如下:

  1. 通过index.model()方法获取当前选定项目所在的模型。
  2. 调用data(index)方法获取当前选定项目的数据。
  3. 使用.toInt()方法将获取的数据转换为整数类型,并将结果存储在名为value的整型变量中。

这段代码通常会在Qt中的视图(例如QListView、QTableView等)中使用,用于从模型中获取特定项目的数据,并进行必要的处理或操作。

问题2:代理类每次只修改一次索引数据吗? 

Qt中的代理类通常是用来处理单个数据项的显示和编辑,而不是整体的数据修改。当涉及到列表视图(如QComboBox、QListView、QTreeView等)中多个数据项的修改时,代理类通常只会处理当前索引对应的数据项的显示和编辑,而不会直接修改整个数据模型。

代理类是用来解决特定单元格或项的展示和编辑问题的,例如在列表中显示不同格式的文本、使用自定义控件进行编辑等。代理类通过重写paint、createEditor、setEditorData和setModelData等方法,来实现对特定数据项的定制显示和编辑行为。

问题3:QcomboBox代理时的过程分析 

用户点击表格时,代理类会调用CreateEdit函数以展示用户选择的值。当用户最终确定索引后,代理会将当前的值设置到编辑器中,然后通过编辑器将值设置到模型中。这样用户就可以通过QComboBox来编辑表格中的数值。

用户选择时的值索引通常是QComboBox中的值。用户在QComboBox中选择一个选项,代理会将该选项在QComboBox中的索引作为值进行处理,并将其设置到编辑器中,然后根据用户的操作将该值传递到模型中。模型中可能保存着与QComboBox中选项对应的具体数值或其他数据,而在代理中会根据索引来获取相应的数据并进行处理

QWidget *JobDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const
{QComboBox*editor=new QComboBox(parent);//设置属性QStringList list={"软件工程师","经理","程序员","助理"};editor->addItems(list);return editor;
}void JobDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
{Q_UNUSED(index);//设置编辑器数据QComboBox*combox=static_cast<QComboBox*>(editor);combox->setCurrentText(index.model()->data(index).toString());
}void JobDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
{//设置模型的数据QComboBox*combox=static_cast<QComboBox*>(editor);QString str=combox->currentText();model->setData(index,str);}

 

JobDelegate::setEditorData 函数中的 index 参数代表的是要编辑的索引,通常是代理所管理的表格模型中的一个特定索引。在这里,index 参数表示要编辑的单元格在模型中的位置,而不是 QComboBox 控件本身的索引。

在这个函数中,index.model() 表示从 index 中获取对应的模型,然后通过 index.model()->data(index) 获取该索引位置的数据,并将其作为文本设置为 QComboBox 的当前文本内容。

因此,index.model() 不是指代 QComboBox 控件自身,而是指代表的是表格模型中的数据。代理类在这里是用来管理如何显示和编辑模型中数据的。

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

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

相关文章

BIO/NIO学习

在传送文件的时候常常出现这么一个问题&#xff0c;就是当客户端的文件全部传送完了之后&#xff0c;服务器没有接收到客户端那边传过的停止信号&#xff0c;所以服务器也就跟着客户端停止运行了&#xff0c;我们可以使用 try {socket.shutdownOutput();} catch (IOException e…

web前端之vue动态访问静态资源、静态资源的动态访问、打包、public、import、URL、Vite

MENU 静态资源与打包规则动态访问静态资源直接导入将静态资存放在public目录中动态导入URL构造函数结束语实践与坑附文 静态资源与打包规则 介绍 Vite脚手架在打包代码的时候&#xff0c;会把源代码里对于静态资源的访问路径转换为打包后静态资源文件的路径。主要的区别是文件指…

ROS 话题通信(C++)

ROS 话题通信&#xff08;C&#xff09; 话题并不只属于发布者或订阅者,而是由ROS系统创建管理的,只要节点向NodeHandle大管家提出的话题发布需求或者话题订阅需求,这个话题就会自动被创建 这段话的核心是解释ROS&#xff08;Robot Operating System&#xff09;中话题&#xf…

go-gin中session实现redis前缀和db库选择+单点登录

分别实现了redigo中自动加前缀和session中自动加前缀 等有空了整理一个demo放到github上&#xff0c;到时候求个小星星 在gin-contrib/sessions/redis库中redis的前缀是被封装起来了&#xff0c;所以自定义前缀没有内部方法在这里我们自己实现一下NewStoreWithDBPrefix方法配…

记录一次开源 MaxKey 安装部署

官方文档&#xff1a;https://www.maxkey.top/doc/docs/intro/ 开源代码&#xff1a;https://toscode.mulanos.cn/dromara/MaxKey 发行版&#xff1a;https://toscode.mulanos.cn/dromara/MaxKey/releases 一、准备工作 yum install -y yum-utils yum-config-manager --add-r…

SwiftUI初探

SwiftUI 虽然出现了好几年(1.0好像2019年出的&#xff0c;还有SPM也是同一年)&#xff0c;现在已经到从1.0到5.0&#xff0c;但受限于对系统的要求(最低iOS13.0,有的要求17.0及以上)&#xff0c;每个版本里面差异也很大&#xff0c;语法和Flutter 的Dart 比较像。空闲之余可以先…

谈谈什么是生成器,它与列表推导式有何区别?以及如何使用Python进行异常处理?

生成器&#xff08;Generator&#xff09;是一种特殊的函数&#xff0c;它一次生成一个值&#xff0c;而不是一次性生成所有值。可以将其视为可恢复函数&#xff0c;在函数执行过程中&#xff0c;yield语句会返回需要的值给调用生成器的地方&#xff0c;然后退出函数。下一次调…

linux定时删除历史日志

在Linux系统中&#xff0c;日志文件是记录系统、应用程序或服务的运行信息、错误消息和警告的重要工具。然而&#xff0c;随着时间的推移&#xff0c;这些日志文件会不断积累&#xff0c;占用大量的磁盘空间。如果不及时清理&#xff0c;可能会导致磁盘空间不足&#xff0c;从而…

5、sqlmap注入post类型+os-shell

题目&#xff1a;青少年&#xff1a;Easy_SQLi 1、打开网页&#xff0c;是一个登入表单 2、判断注入类型&#xff0c;是一个字符注入&#xff0c;使用or直接绕过密码进去了 3、上bp抓取数据包&#xff0c;sqlmmap用post注入走一遍&#xff0c;找到数据库&#xff0c;账号密码&…

如何制定一个有效的现货黄金投资策略(EEtrade)

制定一个有效的现货黄金投资策略涉及多方面的考量。以下是几个步骤和考虑因素&#xff0c;可以帮助您建立一个坚实的投资策略&#xff1a; 1. 设立清晰的投资目标 决定您投资现货黄金的主要目的。是否是为了短期利润&#xff0c;长期保值增值&#xff0c;还是为了投资组合的多…

N的阶乘(高精度)

目录 题目描述 输入格式 输出格式 样例输入 样例输出 思路 参考代码 题目描述 输入正整数n&#xff0c;输出n&#xff01; 输入格式 一个正整数n&#xff0c;n 3000 输出格式 输出n&#xff01; 样例输入 3 样例输出 9 思路 主要就是高精度乘法的模版&#x…

Python中Web开发-Django框架

大家好&#xff0c;本文将带领大家进入 Django 的世界&#xff0c;探索其强大的功能和灵活的开发模式。我们将从基础概念开始&#xff0c;逐步深入&#xff0c;了解 Django 如何帮助开发人员快速构建现代化的 Web 应用&#xff0c;并探讨一些最佳实践和高级技术。无论是初学者还…

Unity3D插件开发教程(二):制作批处理工具

Unity3D插件开发教程&#xff08;二&#xff09;&#xff1a;制作批处理工具 文章来源&#xff1a;Unity3D插件开发教程&#xff08;二&#xff09;&#xff1a;制作批处理工具 - 知乎 (zhihu.com) 声明&#xff1a; 题图来自于Gratisography | Free High Resolution Pictures…

QA测试开发工程师面试题满分问答25: JVM瓶颈分析,举例说明

回答思路 JVM 性能瓶颈概述: JVM (Java Virtual Machine)是 Java 程序运行的基础环境,其性能直接影响到应用程序的整体性能。在实际项目中,我们经常会遇到 JVM 性能瓶颈,导致应用程序出现响应缓慢、CPU 利用率高、内存溢出等问题。因此,分析和诊断 JVM 瓶颈是非常重要的工作,有…

SpringValidation

一、概述&#xff1a; ​ JSR 303中提出了Bean Validation&#xff0c;表示JavaBean的校验&#xff0c;Hibernate Validation是其具体实现&#xff0c;并对其进行了一些扩展&#xff0c;添加了一些实用的自定义校验注解。 ​ Spring中集成了这些内容&#xff0c;你可以在Spri…

小程序使用vant组件库

一:下载组件库 在小程序内npm下载的包 vant组件库官网:快速上手 - Vant Weapp (youzan.github.io) 1)首先有有package.json文件,没有的话则先初始化 即使通过package.json去下载包,也需要有,可以观察下载的包. 2)下载包 3)构建npm包 下载包之后存储在node_modules内,但是我们…

初学者必读:Midjourney AI创作工具的简易使用手册!

在数字化时代&#xff0c;AI的应用不断推动着各个领域的发展。在这些领域中&#xff0c;AI在艺术和设计方面的应用引起了广泛的关注。AI绘画软件作为今年的热门&#xff0c;Midjourney 通过其独特的原理和方便的使用方法&#xff0c;为创作者提供了一个全新的创作逼真绘画的平台…

大模型日报|今日必读的 5 篇大模型论文

大家好&#xff0c;今日必读的大模型论文来啦&#xff01; 1.Meta 领衔&#xff1a;一文读懂视觉语言建模&#xff08;VLM&#xff09; 人们正在尝试将大型语言模型&#xff08;LLMs&#xff09;扩展到视觉领域。从可以引导我们穿越陌生环境的视觉助手&#xff0c;到仅使用高…

富港银行 优惠链接 邀请码 兑换码 优惠码 分享

首次记得一定要点击链接注册&#xff0c;注册开户费50美金 限时&#xff01;优惠开通国际银行账户&#xff01; cbi帐户管理费&#xff1a;10美元/月&#xff0c;余额>500美元&#xff0c;1美元/月/&#xff0c;余额>2000美元&#xff0c;0美元/月。 一定要显示50的时候…

一分钟学习数据安全——数字身份的三种模式

微软首席身份架构师金卡梅隆曾说&#xff1a;互联网的构建缺少一个身份层。互联网的构建方式让你无法得知所连接的人和物是什么。这限制了我们对互联网的使用&#xff0c;并让我们面临越来越多的危险。如果我们坐视不管&#xff0c;将面临迅速激增的盗窃和欺诈事件&#xff0c;…