qt5-入门-自定义委托-简单例子

参考:
Qt 自定义委托_w3cschool
https://www.w3cschool.cn/learnroadqt/ov8h1j4z.html

C++ GUI Programming with Qt 4, Second Edition

本地环境:
win10专业版,64位,Qt 5.12


理论知识

Qt的model/view架构中,view只是1.对model数据的展示 2.处理用户输入。但是view只是讲用户输入委托给delegate处理

在Qt中,委托(Delegate)是一种用于控制如何显示和编辑视图中的数据的机制。它允许我们:对于不同的单元格,可以:

  • 自定义不同的外观,比如使用自定义的图标、颜色或对齐方式
  • 自定义不同的行为,比如为某些单元格提供特殊的编辑器,比如自定义的下拉列表、输入控件

委托和视图之间的区别在于:

  • 视图负责显示和编辑数据,而委托负责定义和实现如何显示和编辑特定单元格。
  • 视图是整个可见区域,如QTableViewQTreeView,而委托是针对特定单元格的。

Qt 4.4版本之后提供了两个可以被继承的 delegate 类:QItemDelegateQStyledItemDelegate。默认的 delegate 是 QStyledItemDelegate

这两个类可以被相互替代,主要区别在于,QStyledItemDelegate 使用当前的风格(style)去绘制组件。所以,在自定义 delegate 或者需要使用 Qt style sheets 时,建议使用 QStyledItemDelegate 作为父类。使用这两个类的代码通常是一样的,除了需要使用 style进行绘制的部份。如果你希望为 view item 自定义绘制函数,最好实现一个自定义的 style。这个你可以通过 QStyle 类来实现。

如果 delegate 没有支持为你的数据类型进行绘制,或者你希望自己绘制 item,那么就可以继承 QStyledItemDelegate 类,并且重写 paint() 或者还需要重写 sizeHint() 函数。paint() 函数会被每一个 item 独立调用,而 sizeHint()函数则可以定义每一个 item 的大小。在重写 paint() 函数的时候,通常需要用 if 语句找到你需要进行渲染的数据类型并进行绘制,其他的数据类型需要调用父类的实现进行绘制。

一个自定义的 delegate 也可以直接提供一个编辑器,而不是使用内置的编辑器工厂(editor item factory)。如果你需要这种功能,那么需要实现一下几个函数:

  • createEditor():返回修改数据的组件;
  • setEditorData():为 editor 提供编辑的原始数据;
  • updateEditorGeometry():保证 editor 显示在 item view 的合适位置以及大小;
  • setModelData():根据 editor 的数据更新 model 的数据。

实现效果

假设有一个table,每个单元格显示的是当前数据的平方值(原始数据是1~5)
在这里插入图片描述
双击单元格,可以编辑,编辑完成后立刻显示。
在这里插入图片描述
在这里插入图片描述

实现

model

#ifndef CUSTOMTABLEMODEL_H
#define CUSTOMTABLEMODEL_H

#include <QAbstractTableModel>

class CustomTableModel : public QAbstractTableModel
{
    Q_OBJECT
public:
    explicit CustomTableModel(QObject* parent = nullptr)
        : QAbstractTableModel(parent)
    {
        // 初始化数据
        m_data << 1 << 2 << 3 << 4 << 5;
    }

    int rowCount(const QModelIndex& parent = QModelIndex()) const override
    {
        return m_data.size();
    }

    int columnCount(const QModelIndex& parent = QModelIndex()) const override
    {
        return 1;
    }

    QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override
    {
        if (!index.isValid())
            return QVariant();

        if (role == Qt::DisplayRole) {
            return m_data.at(index.row());
        }

        return QVariant();
    }

    Qt::ItemFlags flags(const QModelIndex& index) const override
    {
        if (!index.isValid())
            return Qt::NoItemFlags;

        return Qt::ItemIsEditable | QAbstractTableModel::flags(index);
    }

    bool setData(const QModelIndex& index, const QVariant& value, int role = Qt::EditRole) override
    {
        if (index.isValid() && role == Qt::EditRole) {
            m_data.replace(index.row(), value.toInt());
            emit dataChanged(index, index);
            return true;
        }

        return false;
    }

private:
    QList<int> m_data;
};

#endif // CUSTOMTABLEMODEL_H

自定义委托

#ifndef SQUAREDELEGATE_H
#define SQUAREDELEGATE_H

#include <QStyledItemDelegate>
#include <QModelIndex>
#include <QObject>
#include <QSize>
#include <QSpinBox>
#include <QPainter>



class SquareDelegate : public QStyledItemDelegate
{
public:
    QSize sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const override
    {
        return QStyledItemDelegate::sizeHint(option, index);
    }

    void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const override
    {

        if (index.isValid()) {
            int value = index.model()->data(index).toInt();
            QString text = QString::number(value * value);
            painter->save();
            painter->drawText(option.rect, Qt::AlignCenter, text);
            painter->restore();
        } else {
        	// 这是绘制原来的数据。如果原数据和平方值都要显示,可以把这句放在最前面
            QStyledItemDelegate::paint(painter, option, index);
        }
    }

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

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

    void setModelData(QWidget* editor, QAbstractItemModel* model, const QModelIndex& index) const override
    {
        /*
        QSpinBox* spinBox = static_cast<QSpinBox*>(editor);
        int value = spinBox->value();
        model->setData(index, value);
        */

        if (QSpinBox* spinBox = qobject_cast<QSpinBox*>(editor)) {
            int value = spinBox->value();
            model->setData(index, value, Qt::EditRole);
        } else {
            QStyledItemDelegate::setModelData(editor, model, index);
        }
    }

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


};


#endif // SQUAREDELEGATE_H

main

QTableView* tableView = new QTableView;
SquareDelegate* delegate = new SquareDelegate;
// 设置委托
tableView->setItemDelegate(delegate);
CustomTableModel* model = new CustomTableModel;
// 设置模型
tableView->setModel(model);
tableView->show();

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

FastAPI Web框架教程 第14章 部署

14-1 在Linux上安装Python 【环境】 腾讯云服务器 Centos 8 【安装方式】 源码编译安装 安装步骤&#xff1a; 第1步&#xff1a;更新yum源 cd /etc/yum.repos.d/ sed -i s/mirrorlist/#mirrorlist/g /etc/yum.repos.d/CentOS-* sed -i s|#baseurlhttp://mirror.centos.…

RESTful的优点

优点 1.通过url对资源定位&#xff0c;语义清晰&#xff1b; 2.通过HTTP谓词表示不同的操作&#xff0c;接口自描述&#xff1b; 3.可以对GET、PUT、DELETE请求重试&#xff08;幂等的&#xff09;&#xff1b; 4.可以对GET请求做缓存&#xff1b; 5.通过HTTP状态码反映服务器端…

【数据结构】AVL 树

文章目录 1. AVL 树的概念2. AVL 树节点的定义3. AVL 树的插入4. AVL 树的旋转5. AVL 树的验证6. AVL 树的删除7. AVL 树的性能 前面对 map / multimap / set / multiset 进行了简单的介绍【C】map & set&#xff0c;在其文档介绍中发现&#xff0c;这几个容器有个共同点是…

Java面试必问题24:线程池的拒绝策略有哪些 synchronized 和 lock 的区别 (重点)

以上列出的是Java线程池中常见的拒绝策略&#xff0c;具体可以根据实际情况选择合适的拒绝策略&#xff0c;也可以自定义实现RejectedExecutionHandler接口来定义自己的拒绝策略。默认的拒绝策略是AbortPolicy&#xff0c;即直接抛出异常。 最简回答&#xff1a;线程池的拒绝策…

6000000IOPS!FASS×kunpeng920全新突破

实测数据详见下文 网络环境 前端和后端网均采用100GE网络&#xff0c;管理网采用1Gbps以太网。 前端网和后端网通过不同网段隔离&#xff0c;与管理网物理隔离。 软硬件配置 存储端配置&#xff1a; 客户端配置&#xff1a; 软件配置&#xff1a; 存储集群配置&#xff1a; …

EasyExcel 复杂表头的导出(动态表头和静态表头)

问题&#xff1a;如图&#xff0c;1部分的表头是动态的根据日期变化&#xff0c;2部分是数据库对应的字段&#xff0c;静态不变的&#xff1b; 解决方案&#xff1a;如果不看1的部分&#xff0c;2部分内容可以根据实体类注解的方式导出&#xff0c;那么我们是不是可以先将动态表…

选精益制造咨询公司,牢记这几点,轻松避开陷阱!

众所周知&#xff0c;选择一家合适的精益制造咨询公司&#xff0c;可以帮助企业实现转型升级&#xff0c;提升生产效率和市场竞争力。然而&#xff0c;市场上的咨询公司众多&#xff0c;如何选择一家真正专业、有实力的公司&#xff0c;避免踩坑呢&#xff1f; 一、看准公司背景…

MCU友好过渡MPU,米尔基于STM32MP135开发板裸机开发应用笔记

以前微处理器&#xff08;MPU&#xff09;与微控制器&#xff08;MCU&#xff09;是截然不同的两种设备&#xff0c;MPU支持丰富的软件系统&#xff0c;如Linux和相关的软件堆栈&#xff0c;而MCU通常将专注于裸机和RTOS。近年来&#xff0c;随着MCU的性能越来越高&#xff0c;…

前端二维码生成工具小程序:构建营销神器的技术解析

摘要&#xff1a; 随着数字化营销的不断深入&#xff0c;二维码作为一种快速、便捷的信息传递方式&#xff0c;已经广泛应用于各个领域。本文旨在探讨如何通过前端技术构建一个功能丰富、操作简便的二维码生成工具小程序&#xff0c;为企业和个人提供高效的营销支持。 一、引言…

数字化助力乡村振兴:数字乡村展现新活力

目录 一、数字乡村的概念与内涵 二、数字化助力乡村振兴的具体表现 1、促进农村产业升级 2、提升农民生活质量 3、优化农村治理体系 三、数字乡村展现的新活力 1、创新发展模式的活力 2、激发农民内生动力的活力 3、提升乡村整体形象的活力 四、数字乡村发展面临的挑…

记一次Cannot deploy POJO class [xxx$$EnhancerBySpringCGLIB$$xxx]的错误

最近项目上需要使用websocket做服务端&#xff0c;那好说啊&#xff0c;直接springboot集成的websocket 引入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId><versi…

Linux_进程通信_管道_system V共享内存_6

文章目录 一、进程通信分类二、管道1.什么是管道1.原理2.管道的特点 2.匿名管道3.命名管道1.创建命名管道文件 - mkfifo (命令)2.创建命名管道文件 - mkfifo (函数) 三、system V共享内存1.原理2.共享内存函数1.fotk2.shmget1.如何知道有哪些IPC资源 - ipcs &#xff08;命令&a…

k8s笔记28--快速在ubuntu上基于二进制和源码安装containerd

k8s笔记28--快速在ubuntu上基于二进制和源码安装containerd 介绍containerd 安装方法二进制文件安装源码构建安装 注意事项说明 介绍 Containerd是一个工业标准的容器运行时&#xff0c;它强调简单、健壮和可移植性。它可作为Linux和Windows的守护进程&#xff0c;能管理主机系…

Day78:服务攻防-数据库安全RedisCouchDBH2database未授权访问CVE漏洞

目录 前置知识 数据库应用-Redis-未授权访问&CVE漏洞 未授权访问&#xff1a;CNVD-2015-07557 未授权访问-CNVD-2019-21763 未授权访问-沙箱绕过RCE-CVE-2022-0543 数据库应用-Couchdb-未授权越权&CVE漏洞 Couchdb 垂直权限绕过&#xff08;CVE-2017-12635&…

怎么倒放视频教程?3个简单易行方法分享

怎么倒放视频教程&#xff1f;视频倒放是一种创意性的视频编辑方式&#xff0c;通过倒序播放视频内容&#xff0c;可以为观众带来全新的视觉体验。无论是为了制作搞笑视频&#xff0c;还是为了创作具有艺术感的短片&#xff0c;倒放视频都是一个非常实用的技巧。同时&#xff0…

数学矩阵(详解)

矩阵乘法 知阵乘法是《线性代数》中的基础内容&#xff0c;但在考察数学的算法题中也会出现。 本节我们学习基础的矩阵乘法规则。 每个矩阵会有一个行数和一个列数&#xff0c;只有当相乘的两个矩阵的左矩阵的列数等于右矩阵的行数 时&#xff0c;才能相乘&#xff0c;否则不允…

【计算机毕业设计】黄河交通学院教学质量评价系统的设计与实现(付系统源码)

&#x1f389;**欢迎来到我的技术世界&#xff01;**&#x1f389; &#x1f4d8; 博主小档案&#xff1a; 一名来自世界500强的资深程序媛&#xff0c;毕业于国内知名985高校。 &#x1f527; 技术专长&#xff1a; 在深度学习任务中展现出卓越的能力&#xff0c;包括但不限于…

跑步用什么运动耳机?推荐几款跑步时超好用的运动耳机

跑步健身成为了很多都市白领喜欢的运动方式之一&#xff0c;而为专业运动健身领域设计的运动耳机&#xff0c;近年来也受到了越来越多运动爱好者和数码爱好者的关注。相比于传统蓝牙耳机&#xff0c;运动耳机在运动过程中带给用户更舒适和安全的使用体验&#xff0c;因此也受到…

什么是AIGC,AIGC的应用领域有哪些,以及对AIGC的未来展望有什么值得关注的方向

AIGC:人工智能生成内容的深度解析 在数字技术的浪潮中,AIGC(ArtificialIntelligenceGeneratedContent,人工智能生成内容)逐渐崭露头角,成为继专业生产内容(PGC)和用户生产内容(UGC)之后的新型内容创作方式。它不仅改变了内容生产的传统模式,更在多个行业中展现出…

钉钉服务端API报错 43008 参数需要multipart类型

钉钉服务端API报错 43008 参数需要multipart类型 problem 使用媒体文件上传接口&#xff0c;按照文档输入参数&#xff0c;结果返回报错 # 参数 {"access_token": "xxx""type": "image","media": "/Users/xxx/xxx/s…