代理就是一个中间人的意思,也就是model和view之间的一个中间件,它协调两者之间的数据处理,以保证数据在显示层和model层的一致性。
在qt中实现自己的一个代理,一般继承自QItemDelegate类,当然也可以是QAbstractItemDelegate。
在做代理的时候,我们首先要明确一些问题,我们的编辑控件是什么,设置它的值,修改怎么影响model,编辑控件的样式什么样,大小位置是否考虑。在qt中这些需要实现自己代理的方面都以虚函数的形式给出,在实现自己代理的时候,重新实现这些虚函数就行,而调用是自动的,这就是利用C++多态,实现了开闭。
下面给出一个例子
- #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知道这些虚函数是怎么调用的,加深对整个框架运行机制的理解