前言:
委托通过实现 paint()函数和 sizeHint()函数来使它们可以渲染自身的内容。简单的基于部件的委托可以通过子类化 QItemDelegate 来实现。委托的编辑器可以通过两种方式来实现:一种是使用部件来管理编辑过程,另一种是直接处理事件。
Qt 中的标准视图都使用 QItemDelegate 的实例来提供编辑功能,这种委托接口的默认实现为 QListView、QTableView 和 QTreeView 等标准视图的每一个项目提供了普通风格的渲染。标准视图中的默认委托会处理所有的标准角色。可以使用 itemDelegate() 函数获取一个视图中使用的委托,使用 setItemDelegate() 函数可以为一个视图安装一个自定义委托。
自定义委托
实现一个通过使用 QSpinBox 来提供一个编辑功能,显示整数的模型的自定义委托。这里的委托继承自 QItemDelegate,这样不需要编写自定义的显示函数。
class SpinBoxDelegate : public QItemDelegate
{
QWidget *createEditor(QObject *parent, QStyleOptionViewItem &option, QModelIndex &index);
void setEditorData(QWidget *editor, QModelIndex &index);
void setModelData(QWidget *editor, QAbstractItemModel *model, QModelIndex &index);
void updateEditorGeometry(QWidget *editor, QStyleOptionViewItem &option, QModelIndex &index);
}
复制代码
当视图需要编辑器时,它会告知委托为被修改的项目提供一个编辑器部件。
QWidget *SpinBoxDelegate::createEditor(QObject *parent, QStyleOptionViewItem &option, QModelIndex &index)
{
QSpinBox *editor = new QSpinBox(parent);
editor->setMinimum(0);
editor->setMaximum(100);
return editor;
}
复制代码
通过 setEditorData()为编辑器设置数据。委托必须将模型中的数据复制到编辑器中。
void SpinBoxDelegate::setEditorData(QWidget *editor, QModelIndex &index)
{
int value = index.model()->data(index, Qt::EditRole).toInt();
QSpinBox *spinBox = static_cast<QSpinBox *>(editor);
spinBox->setValue(value);
}
复制代码
当用户完成了对 QSpinBox 部件中数据的编辑时,视图会通过调用 setModelData() 函数来告知委托将编辑好的数据存储到模型中。这里调用了 interpretText() 函数来确保获得的是 QSpinBox 中最近更新的数值。标准的 QItemDelegate 类会在完成编辑后发射 closeEditor() 信号来告知视图,视图确保编辑器部件被关闭和销毁。不过这里没有实现这个功能。
void SpinBoxDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, QModelIndex &index)
{
QSpinBox *spinBox = static_cast<QSpinBox *>(editor);
spinBox->interpretText();
int value = spinBox->value();
model->setData(index, value, Qt::EditRole);
}
复制代码
委托需要来管理编辑器的集合布局,必须在创建编辑器以及视图中项目的大小或位置改变时设置它的几何布局,视图使用了一个 QStyleOptionViewItem 对象来提供所有需要的集合布局信息。这里只使用了项目的矩形作为编辑器的几何布局,而对于更复杂的编辑器部件,可能需要将这个矩形进行分隔。
void SpinBoxDelegate::updateEditorGeometry(QWidget *editor, QStyleOptionViewItem &option, QModelIndex &index)
{
editor->setGeometry(option.rect);
}
复制代码
Qt 的很多示例代码,包括一些库的源码,都使用到了委托,所以虽然理解起来有些难,但是还是很厉害的。
评论