9.Delegate类
Concepts
不像MVC模式,Model/View模式并没有单独用来处理事件和用户交互的组件(controller)。通常,视图负责向用户呈现模型中的数据,并处理用户的输入。有时,为了让输入更加灵活,使用Delegate处理交互。Delegate组件提供输入功能,还负责渲染某个Item。Delegate的标准接口在QAbstractItemDelegate中定义。
Delegate希望实现paint()和sizeHint()函数来呈现自己的内容。但是,简单的基于Widget的Delegate通过QItemDelegate子类化,而不是QAbstractItemDelegate,并且有这些函数的默认实现。
Delegate的Editors可以用过Widget管理Edit过程或者直接处理事件,这两种方式实现。第一种方法将在 spin box delegate 例子中实现。
Pixelato例子显示如何专门为TableView创建定制的Delegate。
Using an existing delegate
Qt提供的标准视图都是通过QItemDelegate实例来实现编辑功能。默认的Delegate接口实现,以通常的样式渲染每个标准视图:QListView,QTreeView,QTableView。
所有的standard roles都由标准视图使用的默认Delegate来处理。视图使用的Delegate由itemDelegate()函数返回。setItemDelegate()函数允许您为标准视图安装自定义Delegate。
Delegate举例: 我们显示一个4x2的表格,表格中每个单元都是spinbox。
思考:
1.我们使用QTableView显示这个表格。
2.使用QStandardItemModel,初始化时指定4行2列。
3.渲染每个表格为spinbox,这里就需要QItemDelegate。
4.QItemDeleate实现了paint()和sizeHint()函数。我们不需要重新这2个函数。
5.每个表格变成spinbox,需要实现createEditor()函数。
6.表格中数据改变,需要告诉Model,实现setModelData()函数
7.表格中数据改变,显示也要跟着改变,实现setEditorData()函数。
8.最后数据改变,单元格的空间也可能改变,实现updataEditorGeometry()函数。
代码如下:
spinboxdelegate.h
#ifndef SPINBOXDELEGATE_H #define SPINBOXDELEGATE_H #include <QItemDelegate> class SpinBoxDelegate : public QItemDelegate { Q_OBJECT public: explicit SpinBoxDelegate(QObject *parent = 0); QWidget* createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const; void setEditorData(QWidget *editor, const QModelIndex &index) const; void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const; void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const; signals: public slots: }; #endif // SPINBOXDELEGATE_H
sinboxdelegate.cpp
#include "spinboxdelegate.h" #include <QSpinBox> SpinBoxDelegate::SpinBoxDelegate(QObject *parent) : QItemDelegate(parent) { } QWidget* SpinBoxDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const { QSpinBox *editor = new QSpinBox(parent); editor->setMaximum(100); editor->setMinimum(0); return editor; } void SpinBoxDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const { QSpinBox *spinBox = static_cast<QSpinBox *>(editor); spinBox->interpretText(); int num = index.data(Qt::DisplayRole).toInt(); spinBox->setValue(num); } void SpinBoxDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const { QSpinBox *spinBox = static_cast<QSpinBox *>(editor); int num = spinBox->value(); model->setData(index, QVariant(num), Qt::EditRole); } void SpinBoxDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const { editor->setGeometry(option.rect); }
main.cpp
#include <QTableView> #include <QStandardItemModel> #include <QModelIndex> #include <QApplication> #include <spinboxdelegate.h> int main(int argc, char *argv[]) { QApplication a(argc, argv); QStandardItemModel *standardModel = new QStandardItemModel(4,2); QTableView *tableView = new QTableView; tableView->setModel(standardModel); for(int row = 0; row < 4; row++) { for(int col = 0; col < 2; col++) { QModelIndex index = standardModel->index(row, col, QModelIndex()); standardModel->setData(index, QVariant((row+1)*(col+1))); } } SpinBoxDelegate *delegate = new SpinBoxDelegate; tableView->setItemDelegate(delegate); tableView->show(); return a.exec(); }
程序效果如下: