一.应用场景
当我们希望在视图中添加一些组件时,可以使用到自定义代理。
我们可以在上个案例的基础上来进行修改,需要蔬菜的可以dd我,这里使用了另外一个txt文件
,使用我们上次的源代码需要改。
文本文件的表头是7列,所以我们改成7。
插入和添加行的信息也需要修改。
OK,准备工作就做好了。
二.创建自定义代理类
1.创建一个类
取个名就行了。
2.共有继承父类
在刚刚创建的类的头文件中
记得加头文件
#ifndef QSALAYDELEGATE_H #define QSALAYDELEGATE_H #include <QStyledItemDelegate>//用来自定义代理的父类头文件 class QSalayDelegate:public QStyledItemDelegate { public: QSalayDelegate(); };
3.添加宏
class QSalayDelegate:public QStyledItemDelegate { Q_OBJECT public: QSalayDelegate(); };
4.初始化父类
class QSalayDelegate:public QStyledItemDelegate { Q_OBJECT public: QSalayDelegate(QObject*perant=0); };
在cpp文件中:
QSalayDelegate::QSalayDelegate(QObject*perant):QStyledItemDelegate(perant) { }
5.拿到我们需要重写的虚函数
进入到父类中
将这4个虚函数拿到刚刚创建头文件中!
头文件中
#ifndef QSALAYDELEGATE_H #define QSALAYDELEGATE_H #include <QStyledItemDelegate> class QSalayDelegate:public QStyledItemDelegate { Q_OBJECT public: QSalayDelegate(QObject*perant=0); QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const override; void setEditorData(QWidget *editor, const QModelIndex &index) const override; void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const override; void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const override; }; #endif // QSALAYDELEGATE_H
代理类的准备工作就做好了,接下来就是重点了!
三.实现父类的4个虚函数
1.创建代理组件
可以直接在cpp中生成定义
我们这里是想对薪资来添加一个自定义代理组件,所以我们可以使用SpinBox组件
QWidget *QSalayDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const { QSpinBox *editor=new QSpinBox(parent);//创建一个代理组件 //可以对组件设置一些属性 editor->setMinimum(2000);//最小薪资 editor->setMaximum(100000);//最大薪资 editor->setSingleStep(100);//每次可以加一百 return editor; }
2.设置代理组件数据
我们要想要设置代理组件的数据,我们可以通过拿到模型的数据来设置
void QSalayDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const { QSpinBox *spinBox=static_cast<QSpinBox *>(editor);//因为参数editor的类型是祖宗所以我们要强制类型转换 int value=index.model()->data(index).toUInt();//通过模型索引拿到模型数据 spinBox->setValue(value);//设置代理组件数据 }
看注释哈,我写的这么详细!
3.设置模型数据
我们要想设置模型数据,我们可以先拿到代理的数据来设置
void QSalayDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const { QSpinBox *spinBox=static_cast<QSpinBox *>(editor);//相当于拿到代理组件 spinBox->interpretText();//解析数据,这里相当于转换成整数 int value=spinBox->value();//拿到代理的数据 model->setData(index,value);//设置模型数据 }
4.跟新代理组件的位置
void QSalayDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const { editor->setGeometry(option.rect);//默认的位置就是在单元格的矩形位置 }
四.使用代理类
1.头文件
在mainwindow.h中
#include "qsalaydelegate.h"
2.私有成员
3.视图设置代理
在mainwindow.cpp的构造函数中
//指定代理,通过列来指定,4列就是薪资 ui->tableView->setItemDelegateForColumn(4,&salayDelegate);
运行结果:
这样我们的代理就添加好了!
五.其他列添加代理
1.绩效
准备工作都一样。
①.创建代理
QWidget *QFloatDelegate::createEditor (QWidget *parent,const QStyleOptionViewItem &option,const QModelIndex &index)const { QDoubleSpinBox *editor=new QDoubleSpinBox(parent); editor->setMinimum(0); editor->setMaximum(5); editor->setSingleStep(0.1); editor->setDecimals(1);//设置小数点精度 return editor; }
②设置代理数据
void QFloatDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const { QDoubleSpinBox *spinBox=static_cast<QDoubleSpinBox *>(editor); float value=index.model()->data(index).toFloat(); spinBox->setValue(value); }
③设置模型数据
void QFloatDelegate::setModelData(QWidget *editor,QAbstractItemModel *model,const QModelIndex &index) const { QDoubleSpinBox *spinBox=static_cast<QDoubleSpinBox *>(editor); float value=spinBox->value(); QString str=QString::asprintf("%.1f",value); model->setData(index,value); }
④跟新代理位置
void QFloatDelegate::updateEditorGeometry(QWidget *editor,const QStyleOptionViewItem &option,const QModelIndex &index) const { editor->setGeometry(option.rect); }
⑤使用代理
ui->tableView->setItemDelegateForColumn(5,&floatDelegate);
运行结果:
2.性别和岗位
①.创建代理
QWidget *ComboBoxDelegate::createEditor(QWidget *parent,const QStyleOptionViewItem &option,const QModelIndex &index) const { QComboBox *editor=new QComboBox(parent); editor->addItem("软件工程师"); editor->addItem("高级程序员"); return editor; }
如果我这样写会产生一个问题,那就是只能代理一列,我想要的效果是职业和性别都可以下拉框选择,所有这里我们不能写死了,可以通过成员数据来动态的传值!
可以在类中加入:
并且实现:
void ComboBoxDelegate::setList(QStringList list) { this->list=list; }
QWidget *ComboBoxDelegate::createEditor(QWidget *parent,const QStyleOptionViewItem &option,const QModelIndex &index) const { QComboBox *editor=new QComboBox(parent); editor->addItems(this->list); return editor; }
②设置代理数据
void ComboBoxDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const { QComboBox* comboBox=static_cast<QComboBox*>(editor); comboBox->setCurrentText(index.model()->data(index).toString()); }
③设置模型数据
void ComboBoxDelegate::setModelData(QWidget *editor,QAbstractItemModel *model,const QModelIndex &index) const { QComboBox* comboBox=static_cast<QComboBox*>(editor); model->setData(index,comboBox->currentText()); }
④跟新代理位置
void ComboBoxDelegate::updateEditorGeometry(QWidget *editor,const QStyleOptionViewItem &option,const QModelIndex &index) const { editor->setGeometry(option.rect); }
⑤使用代理
mainwindow.h中要有头文件和添加数据成员
comBoxGender.setList(QStringList{"男","女"}); ui->tableView->setItemDelegateForColumn(1,&comBoxGender); comBoxJobs.setList(QStringList{"软件工程师","项目经理","高级程序员","助理"}); ui->tableView->setItemDelegateForColumn(2,&comBoxJobs);
运行结果:
这个例子就讲了一个代理用在多列!
3.生日
①.创建代理
QWidget *QDateDelegate::createEditor(QWidget *parent,const QStyleOptionViewItem &option,const QModelIndex &index) const { QDateEdit*editor=new QDateEdit(parent); editor->setMinimumDate(QDate(1900,1,1)); editor->setMaximumDate(QDate(2020,1,1)); editor->setCalendarPopup(true);//设置弹出 日历 return editor; }
②设置代理数据
void QDateDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const { QDateEdit *dateEdit=static_cast<QDateEdit *>(editor); QString str=index.model()->data(index).toString(); QDate date=QDate::fromString(str,"yyyy-MM-dd"); dateEdit->setDate(date); }
③设置模型数据
void QDateDelegate::setModelData(QWidget *editor,QAbstractItemModel *model,const QModelIndex &index) const { QDateEdit *dateEdit=static_cast<QDateEdit *>(editor); QDate date=dateEdit->date(); model->setData(index,date.toString("yyyy-MM-dd")); }
④跟新代理位置
void QDateDelegate::updateEditorGeometry(QWidget *editor,const QStyleOptionViewItem &option,const QModelIndex &index) const { QRect rect=option.rect; rect.setWidth(rect.width()*1.5);//将日历代理组件的宽度设为原来的1.5倍 editor->setGeometry(rect); }
⑤使用代理
ui->tableView->setItemDelegateForColumn(2,&dateDelegate);
运行结果:
OK,完结了!
六.总结
主要是知道代理的应用场景,和模板化套路。
优秀的公司赚取利润,伟大的公司赢得人心。