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