一、委托 又叫 自定义代理
有的时候一个列表中的不同列 会使用到不同的 QWidget部件。比如下图(各列的数据类型不同)
? ? ? ? ? ? ? ?
这个时候,就是“自定义代理\委托” 的用武之地!=》类似MFC中list中的自绘功能(不同列中实现Edit、combox、checkbox、link超链接等功能)
二、QT中的委托类 抽象基类
QAbstractItemDelegate-》QItemDelegate
?????????????????????????????????????-》QStyledItemDelegate
QStyledItemDelegate使用Qt Style Sheets来渲染单元格中的数据,这样可以更好地与应用程序的外观保持一致。
三、简述功能
1、
模型:负责“组织”数据;
视图:负责“显示”数据;
委托:负责“修改”数据;
2、委托:在QT的MV模型中,处理特定类型的数据(控制数据的外观和行为)!
定制?数据 的“显示”和“编辑”!
编辑日期,数值、渲染颜色,字体、
支持文本编辑器,下拉列表编辑器等、
更新编辑器的尺寸、证编辑器中的数据是否合法;
3、委托:应用场景
3.1表格和列表视图:编辑单元格的数据、定制单元格外观;
3.2 属性编辑器:创建自定义的属性编辑器;
3.3 文件对话框:定制文件列表的外观;
四、委托类 关键函数
4.1 virtual函数
createEditor:创建用于编辑特定单元格中数据的?编辑器;
setEditorData:编辑器被创建后被调用,用于从数据模型获取数值,然后设置为编辑器的显示值。
setModelData:在编辑器编辑完成后被调用,用于将编辑器中数据更新到数据模型中;
updateEditorGeometry:用于设置编辑器的位置和大小。
一般通过继承 QStyledItemDelegate以上4个函数,便可以实现简单的自定义委托。
4.2 其他函数
destroyEditor:
editorEvent:
helpEvent:
sizeHint:
这些函数并没有重要和非重要之分,需要根据不同的需求实现不同的函数,达到想要的效果。
五、使用委托 实现功能
5.1 委托 实现功能1:创建QSpinBox 编辑器、从数据模型获取值+设置编辑器显示值、将编辑器中值保存的数据模型、设置编辑器位置;
? ? ? ? ? ? ? ? ? ? ? ? ??
delegate.h文件
#ifndef DELEGATE_H
#define DELEGATE_H
#include <QStyledItemDelegate>
//! [0]
class SpinBoxDelegate : public QStyledItemDelegate
{
Q_OBJECT
public:
SpinBoxDelegate(QObject *parent = nullptr);
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;
};
//! [0]
#endif
delegate.cpp文件
#include "delegate.h"
#include <QSpinBox>
//! [0]
SpinBoxDelegate::SpinBoxDelegate(QObject *parent)
: QStyledItemDelegate(parent)
{
}
//! [0]
//! [1]
QWidget *SpinBoxDelegate::createEditor(QWidget *parent,
const QStyleOptionViewItem &/* option */,
const QModelIndex &/* index */) const
{
QSpinBox *editor = new QSpinBox(parent);
editor->setFrame(false);
editor->setMinimum(0);
editor->setMaximum(100);
return editor;
}
//! [1]
//! [2]
void SpinBoxDelegate::setEditorData(QWidget *editor,
const QModelIndex &index) const
{
int value = index.model()->data(index, Qt::EditRole).toInt();
QSpinBox *spinBox = static_cast<QSpinBox*>(editor);
spinBox->setValue(value);
}
//! [2]
//! [3]
void SpinBoxDelegate::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, Qt::EditRole);
}
//! [3]
//! [4]
void SpinBoxDelegate::updateEditorGeometry(QWidget *editor,
const QStyleOptionViewItem &option,
const QModelIndex &/* index */) const
{
editor->setGeometry(option.rect);
}
//! [4]
createEditor函数中:定义了一个 QSpinBox类型的编辑器,并对其进行了简单的初始化和设置;
setEditorData函数中:将模型中index位置的数据拿了出来并保存在了value中,并将value设置到了编辑器中;
setModelData函数中:将编辑器中的数据取出来设置到模型中;
updateEditorGeometry中:对位置进行了设置,editor->setGeometry(option.rect);(不执行这个生成的控件在坐标原点 )
5.2 委托 实现功能2:创建QDateEdit 编辑器、从数据模型获取值+设置编辑器显示值、将编辑器中值保存的数据模型、设置编辑器位置;
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
delegate.cpp文件
#include "delegate.h"
#include <QSpinBox>
#include <QDateEdit>
QDateEdit::QDateEdit(QObject *parent)
: QStyledItemDelegate(parent)
{
}
QWidget *QDateEdit::createEditor(QWidget *parent,
const QStyleOptionViewItem &/* option */,
const QModelIndex &/* index */) const
{
// QSpinBox *editor = new QSpinBox(parent);
// editor->setFrame(false);
// editor->setMinimum(0);
// editor->setMaximum(100);
auto *editor = new QDateEdit(parent);
editor->setDisplayFormat("yyyy-MM-dd");
return editor;
}
void QDateEdit::setEditorData(QWidget *editor,
const QModelIndex &index) const
{
// int value = index.model()->data(index, Qt::EditRole).toInt();
// QSpinBox *spinBox = static_cast<QSpinBox*>(editor);
// spinBox->setValue(value);
auto value = index.model()->data(index, Qt::EditRole).toDate();
QDateEdit *dateEdit = static_cast<QDateEdit*>(editor);
dateEdit->setDate(value);
}
void QDateEdit::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, Qt::EditRole);
auto dateEdit = static_cast<QDateEdit*>(editor);
auto value = dateEdit->date();
model->setData(index,value,Qt::EditRole);
}
void QDateEdit::updateEditorGeometry(QWidget *editor,
const QStyleOptionViewItem &option,
const QModelIndex &/* index */) const
{
editor->setGeometry(option.rect);
}
六、
按照这个思路,那么只要改一下里面的编辑器,就能实现不同的委托。想要实现不同的委托,只要继承QStyledItemDelegate类,并实现相应的函数,就可以实现不同的委托。
密码委托,下拉框委托(QComboBox),颜色选择委托,图标委托等等,甚至包括一些,你自己定义的控件的委托。
?