代理就是一个中间人的意思,也就是model和view之间的一个中间件,它协调二者之间的数据处理,以保证数据在显示层和model层的一致性。app
在qt中实现本身的一个代理,通常继承自QItemDelegate类,固然也能够是QAbstractItemDelegate。框架
在作代理的时候,咱们首先要明确一些问题,咱们的编辑控件是什么,设置它的值,修改怎么影响model,编辑控件的样式什么样,大小位置是否考虑。在qt中这些须要实现本身代理的方面都以虚函数的形式给出,在实现本身代理的时候,从新实现这些虚函数就行,而调用是自动的,这就是利用C++多态,实现了开闭。函数
下面给出一个例子ui
#ifndef SPINBOXDELEGATE_H #define SPINBOXDELEGATE_H #include <QItemDelegate> #include <QModelIndex> #include <QObject> #include <QSize> #include <QSpinBox> #define logger() qDebug() << __FILE__ << __LINE__ << __func__ class SpinBoxDelegate : public QItemDelegate { Q_OBJECT public: SpinBoxDelegate(QObject *parent = 0); /** * @brief createEditor 进入可编辑的状态时,产生的编辑控件 * @param parent 这个控件的上层控件 * @param option 一些控件样式选择 * @param index 所在的索引位置 * @return 编辑控件的指针 */ QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const; /** * @brief setEditorData 进入和推出编辑模式调用,修改view的值 * @param editor 与改变想对应的editor指针 * @param index model中的那个索引改变了值 */ void setEditorData(QWidget *editor, const QModelIndex &index) const; /** * @brief setModelData 退出编辑模式,修改model * @param editor 那个editor改变了 * @param model 想对应的model * @param index 对应的索引 */ void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const; /** * @brief updateEditorGeometry 更新位置 * @param editor * @param option * @param index */ void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const; }; /** 这些虚函数是自动调用的,咱们从新实现这些虚函数来达到控制的效果,能够从新实现的虚函数还有好几个,可是意义都是同样的 */ #endif // SPINBOXDELEGATE_H #include "spinBoxDelegate.h" #include <QtGui> #include <QDebug> SpinBoxDelegate::SpinBoxDelegate(QObject *parent) : QItemDelegate(parent) { } QWidget *SpinBoxDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &/* option */, const QModelIndex &/* index */) const { logger(); QSpinBox *editor = new QSpinBox(parent);//产生一个QSpinBox控件 editor->setMinimum(0); editor->setMaximum(100); return editor; } void SpinBoxDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const { logger(); int value = index.model()->data(index, Qt::EditRole).toInt();//根据index得到model的值 QSpinBox *spinBox = static_cast<QSpinBox*>(editor); spinBox->setValue(value); } void SpinBoxDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const { logger(); 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 { logger(); editor->setGeometry(option.rect); } #include <QApplication> #include <QHeaderView> #include <QItemSelectionModel> #include <QStandardItemModel> #include <QTableView> #include "spinBoxDelegate.h" int main(int argc, char *argv[]) { QApplication app(argc, argv); QStandardItemModel model(4, 2); QTableView tableView; tableView.setModel(&model); SpinBoxDelegate delegate; tableView.setItemDelegate(&delegate); tableView.horizontalHeader()->setStretchLastSection(true); tableView.verticalHeader()->setStretchLastSection(true); for (int row = 0; row < 4; ++row) { for (int column = 0; column < 2; ++column) { QModelIndex index = model.index(row, column, QModelIndex()); model.setData(index, QVariant((row+1) * (column+1))); } } tableView.setWindowTitle(QObject::tr("Spin Box Delegate")); tableView.show(); return app.exec(); }能够根据打印的logger知道这些虚函数是怎么调用的,加深对整个框架运行机制的理解