视图代理(转帖)

  代理就是一个中间人的意思,也就是model和view之间的一个中间件,它协调两者之间的数据处理,以保证数据在显示层和model层的一致性。

                    在qt中实现自己的一个代理,一般继承自QItemDelegate类,当然也可以是QAbstractItemDelegate。

                    在做代理的时候,我们首先要明确一些问题,我们的编辑控件是什么,设置它的值,修改怎么影响model,编辑控件的样式什么样,大小位置是否考虑。在qt中这些需要实现自己代理的方面都以虚函数的形式给出,在实现自己代理的时候,重新实现这些虚函数就行,而调用是自动的,这就是利用C++多态,实现了开闭。

                    下面给出一个例子

                    

  1. #ifndef SPINBOXDELEGATE_H  
  2. #define SPINBOXDELEGATE_H  
  3. #include <QItemDelegate>  
  4. #include <QModelIndex>  
  5. #include <QObject>  
  6. #include <QSize>  
  7. #include <QSpinBox>  
  8.   
  9. #define logger()  qDebug() << __FILE__ << __LINE__ << __func__  
  10.   
  11. class SpinBoxDelegate : public QItemDelegate  
  12. {  
  13.     Q_OBJECT  
  14.   
  15. public:  
  16.     SpinBoxDelegate(QObject *parent = 0);  
  17.     /** 
  18.       * @brief createEditor 进入可编辑的状态时,产生的编辑控件 
  19.       * @param parent 这个控件的上层控件 
  20.       * @param option 一些控件样式选择 
  21.       * @param index 所在的索引位置 
  22.       * @return 编辑控件的指针 
  23.       */  
  24.     QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option,  
  25.                           const QModelIndex &index) const;  
  26.     /** 
  27.       * @brief setEditorData 进入和推出编辑模式调用,修改view的值 
  28.       * @param editor 与改变想对应的editor指针 
  29.       * @param index model中的那个索引改变了值 
  30.       */  
  31.     void setEditorData(QWidget *editor, const QModelIndex &index) const;  
  32.     /** 
  33.       * @brief setModelData 退出编辑模式,修改model 
  34.       * @param editor 那个editor改变了 
  35.       * @param model 想对应的model 
  36.       * @param index 对应的索引 
  37.       */  
  38.     void setModelData(QWidget *editor, QAbstractItemModel *model,  
  39.                       const QModelIndex &index) const;  
  40.     /** 
  41.       * @brief updateEditorGeometry 更新位置 
  42.       * @param editor 
  43.       * @param option 
  44.       * @param index 
  45.       */  
  46.     void updateEditorGeometry(QWidget *editor,  
  47.                               const QStyleOptionViewItem &option, const QModelIndex &index) const;  
  48. };  
  49. /** 
  50.    这些虚函数是自动调用的,我们重新实现这些虚函数来达到控制的效果,可以重新实现的虚函数还有好几个,但是意义都是一样的 
  51.  
  52.    */  
  53.   
  54.   
  55. #endif // SPINBOXDELEGATE_H  
  56. #include "spinBoxDelegate.h"  
  57.   
  58. #include <QtGui>  
  59. #include <QDebug>  
  60.   
  61.   
  62. SpinBoxDelegate::SpinBoxDelegate(QObject *parent)  
  63.     : QItemDelegate(parent)  
  64. {  
  65. }  
  66.   
  67. QWidget *SpinBoxDelegate::createEditor(QWidget *parent,  
  68.                                        const QStyleOptionViewItem &/* option */,  
  69.                                        const QModelIndex &/* index */) const  
  70. {  
  71.     logger();  
  72.   
  73.     QSpinBox *editor = new QSpinBox(parent);//产生一个QSpinBox控件  
  74.     editor->setMinimum(0);  
  75.     editor->setMaximum(100);  
  76.   
  77.     return editor;  
  78. }  
  79.   
  80. void SpinBoxDelegate::setEditorData(QWidget *editor,  
  81.                                     const QModelIndex &index) const  
  82. {  
  83.     logger();  
  84.     int value = index.model()->data(index, Qt::EditRole).toInt();//根据index获得model的值  
  85.   
  86.     QSpinBox *spinBox = static_cast<QSpinBox*>(editor);  
  87.     spinBox->setValue(value);  
  88. }  
  89.   
  90. void SpinBoxDelegate::setModelData(QWidget *editor, QAbstractItemModel *model,  
  91.                                    const QModelIndex &index) const  
  92. {  
  93.     logger();  
  94.     QSpinBox *spinBox = static_cast<QSpinBox*>(editor);  
  95.     spinBox->interpretText();  
  96.     int value = spinBox->value();  
  97.   
  98.     model->setData(index, value, Qt::EditRole);  
  99. }  
  100.   
  101. void SpinBoxDelegate::updateEditorGeometry(QWidget *editor,  
  102.                                            const QStyleOptionViewItem &option, const QModelIndex &/* index */) const  
  103. {  
  104.     logger();  
  105.     editor->setGeometry(option.rect);  
  106. }  
  107. #include <QApplication>  
  108. #include <QHeaderView>  
  109. #include <QItemSelectionModel>  
  110. #include <QStandardItemModel>  
  111. #include <QTableView>  
  112.   
  113. #include "spinBoxDelegate.h"  
  114.   
  115. int main(int argc, char *argv[])  
  116. {  
  117.     QApplication app(argc, argv);  
  118.   
  119.     QStandardItemModel model(4, 2);  
  120.     QTableView tableView;  
  121.     tableView.setModel(&model);  
  122.   
  123.     SpinBoxDelegate delegate;  
  124.     tableView.setItemDelegate(&delegate);  
  125.   
  126.     tableView.horizontalHeader()->setStretchLastSection(true);  
  127.     tableView.verticalHeader()->setStretchLastSection(true);  
  128.   
  129.     for (int row = 0; row < 4; ++row) {  
  130.         for (int column = 0; column < 2; ++column) {  
  131.             QModelIndex index = model.index(row, column, QModelIndex());  
  132.             model.setData(index, QVariant((row+1) * (column+1)));  
  133.         }  
  134.     }  
  135.   
  136.     tableView.setWindowTitle(QObject::tr("Spin Box Delegate"));  
  137.     tableView.show();  
  138.     return app.exec();  
  139. }  


          可以根据打印的logger知道这些虚函数是怎么调用的,加深对整个框架运行机制的理解

posted on 2015-10-23 05:39  alleyonine  阅读(211)  评论(0编辑  收藏  举报

导航