Spin box 托管模型展示了如何为用户创建一个编辑器,用在model/view 架构中,通过重用标准的Qt编辑widget。
model/view架构使用标准的view类提供了了标准的默认的托管类型,在大多数情况下,通过这种托管方式,用户可以选择多种简单的编辑方式如文本编辑,布尔值,或者其他的简单的数据类型,然而,对于特殊的数据类型,需要用定制的托管来定制数据展示的方式,或者允许用户来定义自定的控制方式。
在此例背后的目录中,在Delegate Classes章节中的Model/View Programming overview。
SpinBoxDelegate Class 定义
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;
};
这个托管类描述了如下的功能,如要创建一个用户窗体,在一个视图中显示当前的位置,并且和一个模型进行通信,定制托管可以提供属于它自己的回执代码,通过冲定义paintEvent()函数,同时它还可以重用(支持擦除)用户窗体通过destroyEditor()函数,一个重用的窗体能成为一个多态成员,在构造函数中新建,且在析构函数中销毁。
SpinBoxDelegata类的实现
托管经常是没有实体的,构造函数需要调用基类的构造函数
SpinBoxDelegate::SpinBoxDelegate(QObject *parent)
: QStyledItemDelegate(parent)
{
}
如果这个托管是QStyledItemDelegata的子类,数据是可以会基于默认的样式来显示,我们也不需要提供定制的paintevent().
createEditor()函数返回一个编辑窗体,在这个spinbox类中,只允许生成0-100的整数
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;
}
我们加载了一个事件过滤器在spinbox中,可以确保这个spin box具有和其他托管相同的表现,事件过滤器的实现由其基类提供。
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);
}
这个view将代表一个普通的实例,在我们设置spin box之前我们用static cast
setModelData()功能在这个spin box中读取标题,并且将它写到model中
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);
}
我们调用interpreText()函数来确保我们在spinbox中得到了最新的值
updateEditorGeometry()函数更新这个编辑窗口的结构通过使用应用在风格选项中的信息,下面是托管至少需要做的事情。
void SpinBoxDelegate::updateEditorGeometry(QWidget *editor,
const QStyleOptionViewItem &option,
const QModelIndex &/* index */) const
{
editor->setGeometry(option.rect);
}