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)会在应用程序开发中经常用到的

  • 11
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 13
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

东.'

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值