【QT】自定义代理类

news2025/1/18 2:05:08

目录

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); //创建一个QSpinBox
    editor->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.coloradmin.cn/o/1358027.html

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

相关文章

查询json数组

步骤一&#xff1a;创建表格 首先&#xff0c;我们需要创建一个表格来存储包含JSON对象数组的数据。可以使用以下代码创建一个名为 my_table 的表格&#xff1a; CREATE TABLE my_table (id INT PRIMARY KEY AUTO_INCREMENT,json_data JSON ); 上述代码创建了一个包含两个列的…

人大金仓恒生电子助力湘财证券TA系统国产化升级

近日&#xff0c;人大金仓&恒生电子助力湘财证券TA&#xff08;登记过户&#xff09;系统国产化升级上线&#xff0c;系统在性能、稳定性、安全可靠性等方面均表现良好。自2022年至今&#xff0c;在金仓数据库的支撑下&#xff0c;湘财证券已完成TA及其他近30个系统的升级或…

数据结构学习笔记——查找算法中的树形查找(B树、B+树)

目录 前言一、B树&#xff08;一&#xff09;B树的概念&#xff08;二&#xff09;B树的性质&#xff08;三&#xff09;B树的高度&#xff08;四&#xff09;B树的查找&#xff08;五&#xff09;B树的插入&#xff08;六&#xff09;B树的删除 二、B树&#xff08;一&#xf…

整理的6个Linux运维脚本

整理的6个Linux运维脚本 1、统计/etc/passwd 中能登录的用户&#xff0c;并将对应在/etc/shadow 中第二列密码提取2、查看当前连接到本机的远程IP地址3、检测本机当前用户是否为超级管理员&#xff08;root&#xff09;4、检查指定目录下是否存在对应文件5、查找 Linux 系统中的…

基于数据库和NER构建知识图谱流程记录

文章目录 环境准备拓扑设计构建流程设计文件流设计交互解析算法实现数据库交互NER解析相似度计算 基于数据库的文件生成从数据库中读取字段将字段后处理后保存为文件 基于文件的知识图谱构建bug修改与算法优化图数据库连接问题批量构建知识图谱问题批量删除边问题空值处理问题去…

Java重修第二天—学习”方法“

通过学习本篇文章可以掌握如下知识 1、方法的定义 2、方法在计算机中的执行流程。 3、方法使用时常见问题 4、Java中方法的参数传递机制 5、方法重载 1 方法是什么 方法是一种语法结构&#xff0c;它可以把一段代码实现的某种功能封装起来&#xff0c;以便重复利用。 方…

Selenium-java 定位元素时切换iFrame时的方法

具体方法如下图所示&#xff0c;如果iFrame中嵌套多层iFrame需要逐层定位到需要的那一层iFrame,完成操作后&#xff0c;执行该代码&#xff1a;driver.switchTo() .defaultContent() ; 是返回最顶部的frame

vue封装基础input组件(添加防抖功能)

先看一下效果&#xff1a; // 调用页面 <template><div><!-- v-model&#xff1a;伪双向绑定 --><my-input v-model"inputVal" label"姓名" type"textarea" /></div> </template><script> import…

太阳能组件紫外预处理试验箱

太阳能组件紫外预处理试验箱波长范围&#xff1a;280-400nm用于太阳能光伏组件的温湿度及相类似紫外预处理环境的试验&#xff0c;主要用于太阳能组件材料评估诸如聚合物和保护层等材料抗紫外辐照能力&#xff0c;在预处理试验过程中能够快速、真实地再现阳光、雨、露等环境及对…

【MATLAB】CEEMD_LSTM神经网络时序预测算法

有意向获取代码&#xff0c;请转文末观看代码获取方式~也可转原文链接获取~ 1 基本定义 CEEMD-LSTM神经网络时序预测算法是一种结合了完全扩展经验模态分解&#xff08;CEEMD&#xff09;和长短期记忆神经网络&#xff08;LSTM&#xff09;的时间序列预测方法。 CEEMD是一种改…

【Turtle库】皮卡丘

引言 这段Python代码利用了Turtle图形库来绘制一个卡通角色&#xff0c;看起来像皮卡丘。以下是代码的概述&#xff1a; 导入模块&#xff1a; 代码导入了必要的模块&#xff1a;turtle、random&#xff0c;并将turtle重命名为t以便简洁。 函数定义&#xff1a; infoPrt()函数打…

安全cdn有哪些优势

1. 免备案&#xff1a;在中国大陆地区&#xff0c;进行网站建设需要先进行备案手续&#xff0c;而安全cdn可以避免这一繁琐的步骤&#xff0c;节省时间和精力。 2. 精品线路&#xff1a;安全cdn使用的是覆盖范围更广、速度更快的香港CN2 GIA优化线路。 3. 高速稳定&#xff1a…

局部与整体的关联特性,如图所示

局部与整体的关联特性是指事物的局部部分与整体之间存在一定的关联关系。它强调整体是由局部构成&#xff0c;局部又反向影响整体。具体包括以下几个方面的特性&#xff1a; 互依性&#xff1a;局部与整体相互依赖&#xff0c;一个的变动会影响另一个的变动。局部的变化会对整体…

OSPF基本概念与配置(完整版)

目录 路由分类 OSPF概述 一、OSPF的工作过程 二、报文类型 三、OSPF区域 四、OSPF单区域实验案例 拓扑 需求 配置步骤 配置命令 五、OSPF邻居表解析 六、OSPF路由角色 七、OSPF多区域实验案例 拓扑 需求 配置步骤 配置命令 八、邻居建立失败的原因(已广播型网络…

自制java工具实现 ctrl+c+c 翻译鼠标选中文本

前言 本功能的实现基于这篇笔记 http://t.csdnimg.cn/1I8ln&#xff0c;本文阅读过程中有疑惑都可以查看此笔记 实现思路&#xff1a;检测到按压ctrl c c 后&#xff0c;获取当前剪切板文字&#xff0c;调用百度翻译api。 实现结果&#xff1a; 完整代码在最后 实现过程 1 监控…

TS:类型断言

类型断言好比其他语言中的类型转换&#xff0c;但是不是真正的类型转换方式&#xff0c;之所以不被称为类型转换&#xff0c;是因为转换通常意味着某种运行时的支持。但是&#xff0c;类型断言纯粹是一个编译时语法&#xff0c;同时&#xff0c;它也是一种为编译器提供关于如何…

vivado license申请

AMD: Product Licensing

如何使用CapSolver解决Web爬虫中遇到的CAPTCHA问题

Web爬取是一种强大的技术&#xff0c;用于从网站中提取数据&#xff0c;但经常会遇到一个常见障碍&#xff0c;即CAPTCHA。CAPTCHA是“Completely Automated Public Turing test to tell Computers and Humans Apart”的缩写&#xff0c;旨在防止自动机器人访问网站。然而&…

商品小程序(6.商品详情)

目录 一、获取商品详情数据二、渲染商品详情页的UI结构1、渲染轮播图区域2、实现轮播图预览效果3、渲染商品信息区域4、渲染商品详情信息5、解决商品价格闪烁的问题 三、渲染详情页底部的商品导航区域1、渲染商品导航区域的UI结构2、点击跳转到购物车页面 本章主要完成商品详情…

推荐一款加速器,也可加速github

地址https://github.com/BeyondDimension/SteamTools