一、基本概念
与MVC模式不同,MV视图架构中没有包含一个完全分离的组件来处理与用户的交互。
一般地,视图用来将模型中的数据显示给用户,也用来处理用户的输入。为了获得更高的灵活性,交互可以由委托来执行。
这些组件提供了输入功能,而且也负责渲染一些视图中的个别项目。控制委托的接口在QAbstractItemDelegate
类中定义。
委托通过实现paint()
和sizeHint()
函数来使它们可以渲染自身的内容。然而, 简单的基于部件的委托可以通过子类化QItemDelegate
来实现,而不需要使用QAbstractItemDelegate
,这样可以使用这些函数的默认实现。
委托的编辑器可以通过两种方式实现,一种是使用不见来管理编辑过程,另一种是直接处理事件。下面会讲解第一种方式。
可以参考一下Qt提供的Spin Box Delegate示例程序。
如果想要继承
QAbstractItemDelegate
来实现自定义的渲染操作,也可以参考一下Pixelator示例程序。另外,也可以使用
QStyledItemDelegate
作为基类,这样可以自定义数据的显示,这个可以参考Star Delegate示例程序。这些示例程序都在Item View分类中。
Qt中的标准视图都使用QItemDelegate
的实例来提供编辑功能,这种委托接口的默认实现为QListView
、QTableView
和QTreeView
等标准视图的每一个项目提供了普通风格的渲染。
标准视图中的默认委托会处理所有的标准角色,具体的内容可以在QItemDelegate
类的帮助文档中查看。可以使用itemDelegate()
函数获取一个视图中使用的委托,使用setItemDelegate()
函数可以为一个视图安装一个自定义委托。
二、自定义委托
SpinBoxDelegate.h
cpp
#pragma once
#include <QSpinBox>
#include <QItemDelegate>
class SpinBoxDelegate : public QItemDelegate {
public:
using QItemDelegate::QItemDelegate;
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;
};
SpinBoxDelegate.cpp
cpp
#include "SpinBoxDelegate.h"
QWidget *
SpinBoxDelegate::createEditor(QWidget *parent,
const QStyleOptionViewItem &option,
const QModelIndex &index) const
{
auto editor = new QSpinBox(parent);
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();
auto spinBox = static_cast<QSpinBox *>(editor);
spinBox->setValue(value);
}
void
SpinBoxDelegate::setModelData(QWidget *editor,
QAbstractItemModel *model,
const QModelIndex &index) const
{
auto 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
{
(void)index;
editor->setGeometry(option.rect);
}
用法:
cpp
auto delegate = new SpinBoxDelegate(this);
tableView->setItemDelegate(delegate);