代理就是一箇中間人的意思,也就是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知道這些虛函數是怎麼調用的,加深對整個框架運行機制的理解