这里实现一个委托使用 QSpinBox 来提供编辑功能,主要用于显示整数的模型。
从 QStyledItemDelegate 子类化委托而不是 QAbstractItemDelegate,因为QStyledItemDelegate 已经实现了 paint() 函数。
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;
};
提供编辑器
当视图需要提供一个编辑器时,它会要求委托提供一个适合被修改项目的编辑器小部件。 createEditor() 函数就是用来提供这个小部件的:
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;
}
不需要保留指向编辑器小部件的指针,因为视图负责在不再需要时销毁它。
可以根据视图提供的模型索引创建不同的编辑器。例如,如果有一列整数和一列字符串,则可以根据正在编辑的列返回 QSpinBox 或 QLineEdit。
委托需要提供一个函数来将模型数据复制到编辑器中,setEditorData()就是这个函数。在这个例子中,读取显示角色中存储的数据,并相应地设置了微调框中的值。
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);
}
向模型提交数据
当用户完成编辑时,视图要求委托通过调用 setModelData() 函数将编辑后的值存储在模型中。
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);
}
当视图完成编辑时,委托类通过发出 closeEditor() 信号通知视图。该视图确保编辑器小部件已关闭并销毁。
更新编辑器的几何图形
管理编辑器的几何图形是委托的责任。必须在创建编辑器时以及更改视图中项目的大小或位置时设置几何图形。幸运的是,视图在视图选项对象中提供了所有必要的几何信息。
void SpinBoxDelegate::updateEditorGeometry(QWidget *editor,
const QStyleOptionViewItem &option,
const QModelIndex &/* index */) const
{
editor->setGeometry(option.rect);
}
汇总
#ifndef SPINBOXDELEGATE_H
#define SPINBOXDELEGATE_H
#include <QStyledItemDelegate>
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;
};
#endif // SPINBOXDELEGATE_H
#include "spinboxdelegate.h"
#include <QSpinBox>
SpinBoxDelegate::SpinBoxDelegate(QObject *parent)
: QStyledItemDelegate(parent)
{
}
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;
}
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);
}
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);
}
void SpinBoxDelegate::updateEditorGeometry(QWidget *editor,
const QStyleOptionViewItem &option,
const QModelIndex &/* index */) const
{
editor->setGeometry(option.rect);
}
QStandardItemModel * model = new QStandardItemModel;
model->setColumnCount(2);
model->setRowCount(2);
model->setData(model->index(0,0),1);
model->setData(model->index(0,1),2);
model->setData(model->index(1,0),3);
model->setData(model->index(1,1),4);
QTableView view2;
view2.setModel(model);
view2.setItemDelegate(new SpinBoxDelegate);
view2.show();
