【QT】自定义代理类

目录

1 我们为什么要使用自定义代理类?

2  自定义代理类的基本设计要求

3  自定义代理的功能

4  基于QSpinBox的自定义代理类

5  自定义代理类的使用

1 我们为什么要使用自定义代理类?

        传统的模型-视图框架可以让我们实现逻辑展示相分离,我们只需要关心模型就可以,在模型上做的任何更改都会走动更新到视图上去,其实就是观察者模式。Qt基于传统的模型-视图框架(MVC,model、view、controler),推出了MVD(model、view、delegate)框架。具体有什么用呢?
        如果我们使用QTableView来作为表格控件,显示数据,但是突然有需求需要在里面添加一些交互的控件,例如:按钮、进度条之类的,直接使用模型是无法实现的。可以使用QTableWidget控件可以很轻松的实现,但是这个不支持模型-视图框架。代理的作用就来了,代理可以把控件委托给模型来代理,就可以实现在表格中添加控件进行交互了。

2  自定义代理类的基本设计要求

  Qt中有关代理的几个类的层次结构如图5-12所示。
        QAbstractItemDelegate是所有代理类的抽象基类,QStyledItemDelegate是视图组件使用的缺省的代理类,QItemDelegate也是类似功能的类。QStyledItemDelegate与QItemDelegate的差别在于:QstyledltemDelegate可以使用当前的样式表设置来绘制组件,因此建议使用QStyledItemDelegate作为自定义代理组件的基类。
        不管从QStyledItemDelegate还是QItemDelegate继承设计自定义代理组件,都必须实现如下 的4个函数:
  • createEditor()函数创建用于编辑模型数据的widget组件,如一个QSpinBox组件,或一个 QComboBox组件:
  • setEditorData()函数从数据模型获取数据,供widget组件进行编辑;
  • setModelData()将widget上的数据更新到数据模型;
  • updateEditorGeometry()用于给widget组件设置一个合适的大小。

3  自定义代理的功能

        在实例samp5_3中,导入数据文件进行编辑时,QTableView组件为每个单元格提供的 是缺省的代理编辑组件,就是一个QLineEdit组件。在编辑框里可以输入任何数据,所以比较通用。 但是有些情况下,希望根据数据的类型限定使用不同的编辑组件,例如在samp5_3的实例的数据中, 第1列“测深”是整数,使用QSpinBox作为编辑组件更合适;“垂深”“方位”“总位移”是浮点数, 使用QDoubleSpinBox更合适;而“固井质量”使用 一个QComboBox,从一组列表文字中选择更合适。
        要实现这些功能,就需要为TableView的某列 或某个单元格设置自定义代理组件。本节在实例 samp5_3的基础上,为TableView增加自定义代理 组件功能。设定自定义代理组件之后的TableView 运行时,其编辑状态的效果如图5-11所示。
图5-11 设置自定义代理组件后的TableView编辑时的效果

4  基于QSpinBox的自定义代理类

1、自定义代理类的基本结构
下面设计一个基于QSpinBox类的自定义代理类,用于“测深”数据列的编辑。
定义一个自定义类的名称为QWIntSpinDelegate, 设置基类为QStyledItemDelegate,添加到项目里 。 在头文件qwintspindelegate.h中包含对自定义类QWIntSpinDelegate的定义,在其中添加4个 需要重定义的函数的定义,qwintspindelegate.h的内容如下:
#include    <QStyledItemDelegate>
class QWIntSpinDelegate : public QStyledItemDelegate
{Q_OBJECT
public:QWIntSpinDelegate(QObject *parent=0);
//自定义代理组件必须继承以下4个函数
//创建编辑组件QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option,const QModelIndex &index) const Q_DECL_OVERRIDE;
//从数据模型获取数据,显示到代理组件中void setEditorData(QWidget *editor, const QModelIndex &index) const Q_DECL_OVERRIDE;
//将代理组件的数据,保存到数据模型中void setModelData(QWidget *editor, QAbstractItemModel *model,const QModelIndex &index) const Q_DECL_OVERRIDE;
//更新代理编辑组件的大小void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option,const QModelIndex &index) const Q_DECL_OVERRIDE;
};
自定义代理组件必须重新实现这4个函数,函数的原型都是固定的。
2、createEditor()函数的实现
createEditor()函数用于创建需要的编辑组件,QWIntSpinDelegate类希望创建一个QSpinBox 作为编辑组件,函数的实现如下:
QWidget *QWIntSpinDelegate::createEditor(QWidget *parent,const QStyleOptionViewItem &option, const QModelIndex &index) const
{ //创建代理编辑组件QSpinBox *editor = new QSpinBox(parent); //创建一个QSpinBoxeditor->setFrame(false); //设置为无边框editor->setMinimum(0);editor->setMaximum(10000);return editor;  //返回此编辑器
}
这段代码创建了一个QSpinBox类型的编辑器editor,parent指向视图组件;然后对创建的editor做一些设置,将editor作为函数的返回值。
3、setEditorData()函数
setEditorData()函数用于从数据模型获取数值,设置为编辑器的显示值。当双击一个单元格进 入编辑状态时,就会自动调用此函数,其实现代码如下:
void QWIntSpinDelegate::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); //设置编辑器的数值
}
函数传递来的参数editor指向代理编辑组件,index是关联的数据单元的模型索引。 通过强制类型转换将editor转换为QSpinBox类型组件spinBox,然后将获取的数值设置为 spinBox的值。
4、setModeIData()函数
setModelData()函数用于将代理编辑器上的值更新给数据模型,当用户在界面上完成编辑时会 自动调用此函数,将界面上的数据更新到数据模型。其代码如下:
void QWIntSpinDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
{ //将代理组件的数据,保存到数据模型中QSpinBox *spinBox = static_cast<QSpinBox*>(editor); //强制类型转换spinBox->interpretText(); //解释数据,如果数据被修改后,就触发信号int value = spinBox->value(); //获取spinBox的值model->setData(index, value, Qt::EditRole); //更新到数据模型
}
程序先获取代理组件编辑器里的数值,然后利用传递来的数据模型model和模型索引参数 index将编辑器的最新值更新到数据模型里。
5、updateEditorGeometry()函数
updateEditorGeometry()函数用于为代理组件设置一个合适的大小,函数传递的参数option的 rect变量定义了单元格适合显示代理组件的大小,直接设置为此值即可。代码如下。
void QWIntSpinDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const
{ //设置组件大小editor->setGeometry(option.rect);
}

5  自定义代理类的使用

        同样的,可以创建基于QDoubleSpinBox的自定义代理组件类QWFloatSpinDelegate,用于编 辑浮点数,还可以创建基于QComboBox的自定义组件类QWComboBoxDelegate。在主窗口的类 定义中定义3个代理类的实例变量(省略了其他定义内容):
class MainWindow : public QMainWindow
{Q_OBJECT
private:QWIntSpinDelegate    intSpinDelegate; //整型数QWFloatSpinDelegate  floatSpinDelegate; //浮点数QWComboBoxDelegate   comboBoxDelegate; //列表选择
}

       在MainWindow的构造函数中,为tableView的某些列设置自定义代理组件。增加了自定义代理组件的构造函数代码如下(去掉了初始化状态栏等一些不重要的内容):

MainWindow::MainWindow(QWidget *parent) :QMainWindow(parent),ui(new Ui::MainWindow)
{ui->setupUi(this);theModel = new QStandardItemModel(2,FixedColumnCount,this); //创建数据模型theSelection = new QItemSelectionModel(theModel);//Item选择模型connect(theSelection,SIGNAL(currentChanged(QModelIndex,QModelIndex)),this,SLOT(on_currentChanged(QModelIndex,QModelIndex)));//为tableView设置数据模型ui->tableView->setModel(theModel); //设置数据模型ui->tableView->setSelectionModel(theSelection);//设置选择模型//为各列设置自定义代理组件ui->tableView->setItemDelegateForColumn(0,&intSpinDelegate);  //测深,整数ui->tableView->setItemDelegateForColumn(1,&floatSpinDelegate);  //浮点数ui->tableView->setItemDelegateForColumn(2,&floatSpinDelegate); //浮点数ui->tableView->setItemDelegateForColumn(3,&floatSpinDelegate); //浮点数ui->tableView->setItemDelegateForColumn(4,&comboBoxDelegate); //Combbox选择型
}
为TableView的某一列设置自定义代理组件,使用setltemDelegateForColumn()函数:为某一 行设置自定义代理组件,可使用setltemDelegateForRow()函数:若为整个TableView设置一个自定 义代理组件,则调用setltemDelegate()函数。
如此增加了自定义代理功能后,在编辑“测深”列时,会在单元格的位置出现一个 SpinBox 组件,用于输入整数;在编辑第2至4列的浮点数时,会出现一个DoubleSpinBox组件,用于输 入浮点数;而在编辑“固井质量”列时,会自动出现一个ComboBox组件,用于从下拉列表中选 择一个字符串。

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

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

相关文章

Spring见解 1.2 IOC

2.3.Spring的IOC解决程序耦合 2.3.1.创建工程 2.3.1.1.pom.xml <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0"xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:sc…

Spring 七种事务传播性介绍

作者&#xff1a;vivo 互联网服务器团队 - Zhou Shaobin 本文主要介绍了Spring事务传播性的相关知识。 Spring中定义了7种事务传播性&#xff1a; PROPAGATION_REQUIRED PROPAGATION_SUPPORTS PROPAGATION_MANDATORY PROPAGATION_REQUIRES_NEW PROPAGATION_NOT_SUPPORTED…

八、QLayout 用户基本资料修改(Qt5 GUI系列)

目录 一、设计需求 二、实现代码 三、代码解析 四、总结 一、设计需求 在很多应用程序中会有用户注册或用户编辑信息等界面。本文就设计一个用户信息编辑界面。要求包含用户名、姓名、性别、部门、年龄、头像、个人说明等信息。 二、实现代码 #ifndef DIALOG_H #define D…

springboot中引入AOP切面编程

在Spring Boot 3.0中引入AOP的过程如下所示&#xff1a; 1、首先&#xff0c;确保已经添加了相关依赖。可以通过Maven或Gradle来管理项目的依赖。对于使用Maven构建的项目&#xff0c;需要将以下依赖添加到pom.xml文件中 <dependency><groupId>org.springframewo…

BERT(从理论到实践): Bidirectional Encoder Representations from Transformers【3】

这是本系列文章中的第3弹,请确保你已经读过并了解之前文章所讲的内容,因为对于已经解释过的概念或API,本文不会再赘述。 本文要利用BERT实现一个“垃圾邮件分类”的任务,这也是NLP中一个很常见的任务:Text Classification。我们的实验环境仍然是Python3+Tensorflow/Keras…

2023年度全球重大关基安全事件 TOP 10 | FreeBuf 年度盘点

2023年&#xff0c;针对关键信息基础设施的网络攻击已经演变成为了一个全球性的问题&#xff0c;无论是中、美、俄等国际大国&#xff0c;还是诸多小国/地区&#xff0c;无论是经济发达还是落后&#xff0c;都无法保证绝对免疫关键基础设施的攻击。为了保障国家安全和社会稳定&…

力扣-42.接雨水

题目&#xff1a; 给定 n 个非负整数表示每个宽度为 1 的柱子的高度图&#xff0c;计算按此排列的柱子&#xff0c;下雨之后能接多少雨水。 示例 1&#xff1a; 输入&#xff1a;height [0,1,0,2,1,0,1,3,2,1,2,1] 输出&#xff1a;6 解释&#xff1a;上面是由数组[0,1,0,2…

Windows PowerShell的安全目标——安全警报

Windows PowerShell的安全目标——安全警报 1. 保证Shell安全 ​ 自从2006年年底PowerShell发布以来&#xff0c;微软在安全和脚本方面并没有取得很好的名声。毕竟那个时候&#xff0c;**VBScript和Windows Script Host(WSH)**是两个最流行的病毒和恶意软件的载体&#xff0c…

Linux_CentOS_7.9_MySQL_5.7配置数据库服务开机自启动之简易记录

前言&#xff1a; 作为运维保障&#xff0c;都无法准确预估硬件宕机的突发阶段&#xff0c;其生产数据实时在产出&#xff0c;那作为dba数据库服务的其重要性、必要性就突显而出。这里拿虚拟机试验做个配置记录&#xff0c;便于大家学习参考。 # 如出现服务器重启后登入报错无…

彻底理解前端安全面试题(4)—— 中间人攻击,详解 http 和https 的中间人攻击实例,建议收藏(含源码)

前言 前端关于网络安全问题看似高深莫测&#xff0c;其实来来回回就那么点东西&#xff0c;我总结一下就是 3 1 4&#xff0c;3个用字母描述的【分别是 XSS、CSRF、CORS】 一个中间人攻击。当然 CORS 同源策略是为了防止攻击的安全策略&#xff0c;其他的都是网络攻击。除…

docker-compose Install spug 3

前言 Spug 面向中小型企业设计的轻量级无 Agent 的自动化运维平台,整合了主机管理、主机批量执行、主机在线终端、文件在线上传下载、应用发布部署、在线任务计划、配置中心、监控、报警等一系列功能。 创建一键安装spug 脚本 自动化脚本兼容(ubuntu,RedHat系列及复刻系列,…

spug发布问题汇总记录

问题导览 1. [vite]: Rollup failed to resolve import "element-plus" from "src/main.js". 项目框架简介 vue3viteelement-plus 解决方案 - 1. 配置淘宝镜像源&#xff1a;npm config set registry https://registry.npm.taobao.org/ - 2. npm inst…

SpringBoot从配置文件中获取属性的方法

方式一&#xff1a;Value 基本类型属性注入&#xff0c;直接在字段上添加Value("${xxx.xxx}")即可&#xff0e;注意这里用的是$&#xff0c;而不是#&#xff0c;Value注入的属性&#xff0c;一般其他属性没有关联关系。 配置文件 user:name: Manaphyage: 19sex: m…

性能优化-OpenMP基础教程(四)-全面讲解OpenMP基本编程方法

本文主要介绍OpenMP编程的编程要素和实战&#xff0c;包括并行域管理详细实战、任务分担详细实战。 &#x1f3ac;个人简介&#xff1a;一个全栈工程师的升级之路&#xff01; &#x1f4cb;个人专栏&#xff1a;高性能&#xff08;HPC&#xff09;开发基础教程 &#x1f380;C…

Prometheus 不能访问k8s的中的一些metrics的问题(controller-manager、scheduler、etcd)

主要有三个点 controller-manager、scheduler、etcd 参考&#xff1a; https://www.cnblogs.com/ltaodream/p/15448953.html kube-scheduler 在每台master节点执行 vim /etc/kubernetes/manifests/kube-scheduler.yaml 将 --bind-address127.0.0.1 改为 --bind-address…

OpenAI ChatGPT-4开发笔记2024-05:windows下anaconda中设置visual studio code workspace

这里写自定义目录标题 1 安装anaconda和vscode2 Create an Anaconda Environment3 select Python Interpreter4 Workspace5 Open Workspace With File6 开发文件夹加入workspace7 美化 1 安装anaconda和vscode 标配。 2 Create an Anaconda Environment conda create --name…

Python字典操作指南,掌握编程中必备的数据结构!

更多Python学习内容&#xff1a;ipengtao.com 字典&#xff08;Dictionary&#xff09;是Python中一种非常重要和常用的数据结构&#xff0c;它用于存储键-值对的数据。在Python中&#xff0c;字典是可变&#xff08;Mutable&#xff09;的、无序&#xff08;Unordered&#xf…

计算机视觉入门与调优

大家好啊&#xff0c;我是董董灿。 在 CSDN 上写文章写了有一段时间了&#xff0c;期间不少小伙伴私信我&#xff0c;咨询如何自学入门AI&#xff0c;或者咨询一些AI算法。 90%的问题我都回复了&#xff0c;但有时确实因为太忙&#xff0c;没顾得过来。 在这个过程中&#x…

Go调用jenkins api执行流水线构建与停止

用到的库&#xff1a; "github.com/bndr/gojenkins" 代码如下&#xff0c;一次到位&#xff1a; import ("context""fmt""time""github.com/bndr/gojenkins" )// 构建指定任务 func buildJob(ctx context.Context, jenkins…

Spark调优解析-sparkshuffle和程序开发优化2(七)

1Shuffle调优 1.1调优概述 大多数Spark作业的性能主要就是消耗在了shuffle环节&#xff0c;因为该环节包含了大量的磁盘IO、序列化、网络数据传输等操作。因此&#xff0c;如果要让作业的性能更上一层楼&#xff0c;就有必要对shuffle过程进行调优。但是也必须提醒大家的是&a…