当前位置: 首页 > news >正文

Qt5开发从入门到精通——第八篇四节( 模型/视图结构—— 代理 (Delegate))

CSDN话题挑战赛第2期
参赛话题:学习笔记

欢迎小伙伴的点评✨✨,相互学习c/c++应用开发。🍳🍳🍳
博主🧑🧑 本着开源的精神交流Qt开发的经验、将持续更新续章,为社区贡献博主自身的开源精神👩‍🚀

前言

本章节会给大家带来模型/视图结构—— 代理 (Delegate)的开发实例详解。

一、代理 (Delegate)概述

在表格中嵌入各种不同控件,通过表格中的控件对编辑的内容进行限定 。 通常情况下,采用这种在表格中插入控件的方式,控件始终显示。当表格中控件数目较多时,将影响表格的美观 。 此时,可利用 Delegate 的方式实现同样的效果,控件只有在需要编辑数据项时才会显示,从而解决了所遇到的上述问题 。

二、效果实例

图一
在这里插入图片描述
图二
在这里插入图片描述

新建 test.txt文本另存为格式ANSI 并将以下内容拷贝到文本中,并放入到构建文件build-Delegate-Desktop_Qt_5_12_2_MinGW_32_bit-Debug中

Tom, 1977-01-05, 工人,1500
Jack, 1978-12-23, 医生,3000
Alice, 1980-04-06, 军人,2500
John, 1983-09-25, 律师,5000

三、原码解析

combodelegate.h

#ifndef COMBODELEGATE_H
#define COMBODELEGATE_H

#include <QItemDelegate>
#include <QComboBox>
/*ComboDelegate 的类声明与 DateDelegate 类似,需要重定义的函数也一样 。*/
class ComboDelegate : public QItemDelegate
{
    Q_OBJECT
public:
    ComboDelegate(QObject *parent= 0);
    QWidget *createEditor(QWidget *parent,const QStyleOptionViewItem &option,const
    QModelIndex &index) const;
    void setEditorData(QWidget *editor, const QModelIndex &index) const;
    void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const;
    void updateEditorGeometry (QWidget *editor, const QStyleOptionViewItem &option,const QModelIndex &index) const;
};
#endif // COMBODELEGATE_H

datedelegate.h

#ifndef DATEDELEGATE_H
#define DATEDELEGATE_H

#include <QItemDelegate>
/*DateDelegate 继承自 QItemDelegate 类*/
class DateDelegate : public QItemDelegate
{
    Q_OBJECT
public:
    DateDelegate(QObject *parent= 0);
    QWidget *createEditor (QWidget *parent, const QStyleOptionViewItem & option,
    const QModelIndex &index) const; //完成创建控件的工作,创建由参数中的 QModellndex 对象指定的表项数据的编辑控件,并对控件的内容进行限定。
    //设置控件显示的数据,将 Model 中的数据更新至 Delegate 中,相当千一个初始化工作 。
    void setEditorData(QWidget *editor, const QModelIndex &index) const;
    // (b)
    void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const; //将 Delegate 中对数据的改变更新至 Model 中
    void updateEditorGeometry (QWidget *editor, const QStyleOptionViewItem &option,
    const QModelIndex &index) const; //更新控件区的显示

};

#endif // DATEDELEGATE_H

spindelegate.h

#ifndef SPINDELEGATE_H
#define SPINDELEGATE_H

#include <QItemDelegate>
#include <QSpinBox>

/*使用 QSpinBox 控件实现对收入的输入编辑,调用自定义的 Delegate 来实现。
SpinDelegate 类的实现与 ComboDelegate 类的实现类似*/
class SpinDelegate : public QItemDelegate
{
    Q_OBJECT
public:
    SpinDelegate(QObject *parent= 0);
    QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option,
    const QModelIndex &index) const;
    void setEditorData(QWidget *editor, const QModelIndex &index) const;
    void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &indEex) const;
    void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option,
    const QModelIndex &index) const;
};

#endif // SPINDELEGATE_H

combodelegate.cpp

#include "combodelegate.h"

ComboDelegate::ComboDelegate(QObject *parent)
{

}

/*createEditor()函数中创建了 一个 QComboBox 控件,并插入可显示的条目,安装事件过滤器 。*/
QWidget *ComboDelegate::createEditor(QWidget *parent,const QStyleOptionViewItem &/*option*/,const QModelIndex &/*index*/) const
{
    QComboBox *editor= new QComboBox(parent);
    editor->addItem(" 工人") ;
    editor->addItem(" 农民") ;
    editor->addItem(" 医生") ;
    editor->addItem(" 律师") ;
    editor->addItem(" 军人") ;
    editor->installEventFilter(const_cast<ComboDelegate*>(this));
    return editor;

}
/*setEditorData() 函数中更新了 Delegate 控件中的数据显示,*/
void ComboDelegate::setEditorData (QWidget *editor, const QModelIndex &index)const
{
    QString str =index .model() ->data (index) . toString ();
    QComboBox *box= static_cast<QComboBox*>(editor);
    int i=box->findText(str);
    box->setCurrentIndex(i);
}
/*setModelData() 函数中更新了 Model 中的数据.*/
void ComboDelegate::setModelData (QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
{
    QComboBox *box= static_cast<QComboBox*>(editor);
    QString str = box->currentText () ;
    model->setData(index,str);
}


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

datedelegate.cpp

#include "datedelegate.h"
#include <QDateTimeEdit>
DateDelegate::DateDelegate(QObject *parent)
{

}
QWidget *DateDelegate::createEditor(QWidget *parent,const QStyleOptionViewItem &/*option*/,const QModelIndex &/*index*/) const
{
    QDateTimeEdit *editor= new QDateTimeEdit(parent); //新建一个 QDateTimeEdit 对象作为编辑时的输入控件 。
    editor->setDisplayFormat ("yyyy-MM-dd"); //设置该 QDateTimeEdit 对象的显示格式为yyyy-MM-dd, 此为 ISO 标准显示方式。
    editor->setCalendarPopup (true); //设置日历选择的显示以 Popup 的方式,即下拉菜单方式显示 。
    editor->installEventFilter(const_cast<DateDelegate*>(this));
    // 调用 QObject 类的 instal!EventFilter()函数安装事件过滤器,使 DateDelegate 能够捕获 QDateTimeEdit 对象的事件 。
    return editor;
}

void DateDelegate::setEditorData(QWidget *editor,const QModelIndex &index) const
{
    /*获取指定 index 数据项的数据 。
调用 QModellndex 的 model()函数可获得提供 index 的 Model 对象, data()函数返回的是一个
QVariant 对象, toString() 函数将它转换为 一 个 QString 类型数据 。*/
    QString dateStr= index .model() ->data (index).toString (); 
    /*通过 QDate 的 fromString()函数将
以 QString 类型表示的日期数据转换为 QDate 类型 。 Qt::ISODate 表示 QDate 类型的日期是以 ISO
格式保存的,这样最终转换获得的 QDate 数据也是 ISO 格式,使控件显示与表格显示保待一致 。*/
    QDate date = QDate::fromString(dateStr,Qt::ISODate); 
    /*将 editor 转换为 QDateTimeEdit
对象,以获得编辑控件的对象指针 。*/
    QDateTimeEdit *edit=static_cast<QDateTimeEdit*>(editor);//(c)
    edit->setDate (date);
}

void DateDelegate::setModelData(QWidget *editor,QAbstractItemModel *model,const QModelIndex &index) const
{
    QDateTimeEdit *edit=static_cast<QDateTimeEdit*> (editor); //通过紧缩转换获得编辑控件的对象指针。
    QDate date = edit->date (); // 获得编辑控件中的数据更新 。
    model->setData(index,QVariant(date.toString(Qt::ISODate))); //调用 setData()函数将数据修改更新到 Model 中。
}

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


main.cpp

#include "datedelegate.h"
#include "combodelegate.h"
#include "spindelegate.h"
#include <QApplication>
#include <QStandardItemModel>
#include <QTableView>
#include <QFile>
#include <QTextStream>
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    QStandardItemModel model(4,4);
    QTableView tableView;
    tableView.setModel(&model);
    DateDelegate dateDelegate;
    tableView.setItemDelegateForColumn(1,&dateDelegate);
    ComboDelegate comboDelegate;
    tableView.setItemDelegateForColumn(2,&comboDelegate);
    SpinDelegate spinDelegate;
    tableView.setItemDelegateForColumn(3,&spinDelegate);

    model.setHeaderData(0,Qt::Horizontal,QObject::tr("姓名")) ;
    model.setHeaderData(1,Qt::Horizontal,QObject::tr("生日")) ;
    model.setHeaderData(2,Qt::Horizontal,QObject::tr("职业")) ;
    model.setHeaderData(3,Qt::Horizontal,QObject::tr("收入")) ;
    QFile file("test.txt");  //打开文件用于遍历
    if (file.open(QFile::ReadOnly|QFile::Text))
    {
        QTextStream stream(&file);
        QString line;
        model.removeRows(0,model.rowCount(QModelIndex()),QModelIndex());
        int row =0;
        do
        {
            line=stream.readLine();
            if (!line.isEmpty())
            {
                model.insertRows(row, 1, QModelIndex ()) ;
                QStringList pieces= line.split(",",QString::SkipEmptyParts);
                model. setData (model. index (row, 0, QModelIndex ()), pieces
                .value(0));
                model. setData (model. index (row, 1, QModelIndex ()), pieces
                .value(1));
                model. setData (model. index (row, 2, QModelIndex ()), pieces
                .value(2));
                model. setData (model. index (row, 3, QModelIndex ()), pieces
                .value(3));

                row++;
            }

        }while (!line.isEmpty ());

        file. close () ;
    }


    tableView.setWindowTitle(QObject::tr("Delegate"));
    tableView.resize(440,200);
    tableView.show();
    return a.exec();

}

spindelegate.cpp

#include "spindelegate.h"

/*使用 QSpinBox 控件实现对收入的输入编辑,调用自定义的 Delegate 来实现。
SpinDelegate 类的实现与 ComboDelegate 类的实现类似*/
SpinDelegate::SpinDelegate(QObject *parent): QItemDelegate(parent)
{

}
QWidget *SpinDelegate::createEditor(QWidget *parent,const QStyleOptionViewItem &/*option*/,const QModelIndex &/*index*/) const
{
    QSpinBox *editor= new QSpinBox(parent);
    editor->setRange(0,10000);
    editor->installEventFilter(const_cast<SpinDelegate*>(this));
    return editor;
}
void SpinDelegate::setEditorData (QWidget *editor, const QModelIndex &index)const
{
    int value =index.model()->data(index) .toInt();
    QSpinBox *box= static_cast<QSpinBox*>(editor);
    box->setValue(value);
}

void SpinDelegate::setModelData (QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
{
    QSpinBox *box= static_cast<QSpinBox*>(editor);
    int value= box->value();
    model->setData(index,value);
}
void SpinDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option,const QModelIndex &index) const
{
    editor->setGeometry(option.rect);
}

四、总结

模型/视图结构—— 代理 (Delegate)会在应用程序开发中经常用到的

相关文章:

  • mysql 5.7占用内存大优化
  • 【RabbitMQ】什么是RabbitMQ?RabbitMQ有什么用?应用场景有那些?
  • Unity Metaverse(六)、关于Avatar换装系统的示例工程
  • Vue 3 快速上手
  • 30、根据官方教程详解嵌套类、内部类、静态嵌套类、局部类、匿名类 ...
  • 【Java牛客刷题】入门篇(05)
  • docker入门
  • 【NodeJs-5天学习】第四天存储篇① ——安装使用mysql 8.0
  • 【Verilog 流水线设计】以全加器为例阐述流水线设计的影响
  • spring boot 使用Mybatis-plus的查询方法
  • nginx中root和alias的区别
  • pytorch深度学习训练模板
  • 【Qt+FFMPEG】 - 封装 解码音视频 线程
  • Arduino框架下最便宜的开发芯片-CH552初探
  • Java高并发编程实战5,异步注解@Async自定义线程池
  • [译]如何构建服务器端web组件,为何要构建?
  • Bytom交易说明(账户管理模式)
  • Fundebug计费标准解释:事件数是如何定义的?
  • JavaScript学习总结——原型
  • Java读取Properties文件的六种方法
  • Less 日常用法
  • linux安装openssl、swoole等扩展的具体步骤
  • magento2项目上线注意事项
  • React系列之 Redux 架构模式
  • vue2.0一起在懵逼的海洋里越陷越深(四)
  • 基于组件的设计工作流与界面抽象
  • 记一次删除Git记录中的大文件的过程
  • 开年巨制!千人千面回放技术让你“看到”Flutter用户侧问题
  • 手写一个CommonJS打包工具(一)
  • 云栖大讲堂Java基础入门(三)- 阿里巴巴Java开发手册介绍
  • 在Mac OS X上安装 Ruby运行环境
  • 东超科技获得千万级Pre-A轮融资,投资方为中科创星 ...
  • ​configparser --- 配置文件解析器​
  • #etcd#安装时出错
  • #Linux(make工具和makefile文件以及makefile语法)
  • ( 10 )MySQL中的外键
  • (14)目标检测_SSD训练代码基于pytorch搭建代码
  • (14)学习笔记:动手深度学习(Pytorch神经网络基础)
  • (6)【Python/机器学习/深度学习】Machine-Learning模型与算法应用—使用Adaboost建模及工作环境下的数据分析整理
  • (C语言)字符分类函数
  • (附源码)springboot金融新闻信息服务系统 毕业设计651450
  • (免费领源码)python#django#mysql校园校园宿舍管理系统84831-计算机毕业设计项目选题推荐
  • (强烈推荐)移动端音视频从零到上手(下)
  • (十一)c52学习之旅-动态数码管
  • (算法)Travel Information Center
  • (转)JAVA中的堆栈
  • ***linux下安装xampp,XAMPP目录结构(阿里云安装xampp)
  • .Net Attribute详解(上)-Attribute本质以及一个简单示例
  • .net core IResultFilter 的 OnResultExecuted和OnResultExecuting的区别
  • .NET Core中Emit的使用
  • .NET高级面试指南专题十一【 设计模式介绍,为什么要用设计模式】
  • .NET项目中存在多个web.config文件时的加载顺序
  • .NET运行机制
  • .NET中两种OCR方式对比
  • @ComponentScan比较