视图代理

来源:互联网 发布:淘宝天猫买药可靠吗 编辑:程序博客网 时间:2024/06/01 10:34

                    代理就是一个中间人的意思,也就是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_OBJECTpublic:    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知道这些虚函数是怎么调用的,加深对整个框架运行机制的理解