溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

QT MVC 技術(shù)Model/View初探

發(fā)布時間:2020-07-29 12:08:05 來源:網(wǎng)絡(luò) 閱讀:1484 作者:WZM3558862 欄目:開發(fā)技術(shù)

 

Model/View實現(xiàn)表格技術(shù)


[+]

一、簡介

       Model/View結(jié)構(gòu)使數(shù)據(jù)管理與相應(yīng)的數(shù)據(jù)顯示相互獨立,并提供了一系列標(biāo)準(zhǔn)的函數(shù)接口和用于Model模塊與View模塊之間的通信。它從MVC演化而來,MVC由三種對象組成,Model是應(yīng)用程序?qū)ο?,View是它的屏幕表示,Controller定義了用戶界面如何對用戶輸入進行響應(yīng)。把MVC中的View和Controller合在一起,就形成了Model/View結(jié)構(gòu)。

二、運行圖

(1)為了靈活對用戶的輸入進行處理,引入了Delegate,Model、View、Delegate三個模塊之間通過信號與槽機制實現(xiàn),當(dāng)自身的狀態(tài)發(fā)生改變時會發(fā)出信號通知其他模塊。它們間的關(guān)系如下圖1所示。

QT MVC 技術(shù)Model/View初探

       QAbstractItemModel是所有Model的基類,但一般不直接使用QAbstractItemModel,而是使用它的子類。Model模塊本身并不存儲數(shù)據(jù),而是為View和Delegate訪問數(shù)據(jù)提供標(biāo)準(zhǔn)的接口。

       View模塊從Model中獲得數(shù)據(jù)項顯示給用戶,Qt提供了一些常用的View模型,如QTreeView、QTableView和QListView。

       Delegate的基本接口在QAbstractItemDelegate類中定義,通過實現(xiàn)paint()和sizeHint()以達到渲染數(shù)據(jù)項的目的。

(2)程序運行圖如下圖2所示。

QT MVC 技術(shù)Model/View初探

三、詳解

1、表格中嵌入控件

利用Delegate的方式實現(xiàn)表格中嵌入各種不同控件的效果,控件在需要編輯數(shù)據(jù)項時才出現(xiàn)。

(1)插入日歷編輯框QDateLineEdit


[cpp] view plain copy

  1. #ifndef DATEDELEGATE_H  

  2. #define DATEDELEGATE_H  

  3.   

  4. #include <QtGui>  

  5.   

  6. class DateDelegate : public QItemDelegate  

  7. {  

  8.     Q_OBJECT  

  9.   

  10. public:  

  11.     DateDelegate(QObject *parent = 0);  

  12.   

  13.     QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option,  

  14.                            const QModelIndex &index) const;  

  15.   

  16.     void setEditorData(QWidget *editor, const QModelIndex &index) const;  

  17.     void setModelData(QWidget *editor, QAbstractItemModel *model,  

  18.                        const QModelIndex &index) const;  

  19.   

  20.     void updateEditorGeometry(QWidget *editor,  

  21.          const QStyleOptionViewItem &option, const QModelIndex &index) const;  

  22. };  

  23.   

  24. #endif  

[cpp] view plain copy

  1. #include "datedelegate.h"  

  2.   

  3. DateDelegate::DateDelegate(QObject *parent)  

  4.     : QItemDelegate(parent)  

  5. {  

  6. }  

  7.   

  8. QWidget *DateDelegate::createEditor(QWidget *parent,  

  9.     const QStyleOptionViewItem &/* option */,  

  10.     const QModelIndex &/* index */const  

  11. {  

  12.     QDateTimeEdit *editor = new QDateTimeEdit(parent);  

  13.     editor->setDisplayFormat("yyyy-MM-dd");  

  14.     editor->setCalendarPopup(true);  

  15.     editor->installEventFilter(const_cast<DateDelegate*>(this));  

  16.   

  17.     return editor;  

  18. }  

  19.   

  20. void DateDelegate::setEditorData(QWidget *editor,  

  21.                                      const QModelIndex &index) const  

  22. {  

  23.     QString dateStr = index.model()->data(index).toString();  

  24.     QDate date = QDate::fromString(dateStr,Qt::ISODate);  

  25.   

  26.     QDateTimeEdit *edit = static_cast<QDateTimeEdit*>(editor);  

  27.     edit->setDate(date);  

  28. }  

  29.   

  30. void DateDelegate::setModelData(QWidget *editor, QAbstractItemModel *model,  

  31.                                     const QModelIndex &index) const  

  32. {  

  33.     QDateTimeEdit *edit = static_cast<QDateTimeEdit*>(editor);  

  34.     QDate date = edit->date();  

  35.   

  36.     model->setData(index, QVariant(date.toString(Qt::ISODate)));  

  37. }  

  38.   

  39. void DateDelegate::updateEditorGeometry(QWidget *editor,  

  40.     const QStyleOptionViewItem &option, const QModelIndex &/* index */const  

  41. {  

  42.     editor->setGeometry(option.rect);  

  43. }  

       分析:DateDelegate繼承QItemDelegate,一般需要重定義聲明中的幾個虛函數(shù)。createEditor()函數(shù)完成創(chuàng)建控件的工作;setEditorDate()設(shè)置控件顯示的數(shù)據(jù),把Model數(shù)據(jù)更新至Delegate,相當(dāng)于初始化工作;setModelDate()把Delegate中對數(shù)據(jù)的更改更新至Model中;updateEditor()更析控件區(qū)的顯示。


(2)插入下拉列表框QComboBox


[cpp] view plain copy

  1. #include "combodelegate.h"  

  2.   

  3. ComboDelegate::ComboDelegate(QObject *parent)  

  4.     : QItemDelegate(parent)  

  5. {  

  6. }  

  7.   

  8. QWidget *ComboDelegate::createEditor(QWidget *parent,  

  9.     const QStyleOptionViewItem &/* option */,  

  10.     const QModelIndex &/* index */const  

  11. {  

  12.     QComboBox *editor = new QComboBox(parent);  

  13.     editor->addItem(QString::fromLocal8Bit("工人"));  

  14.     editor->addItem(QString::fromLocal8Bit("農(nóng)民"));  

  15.     editor->addItem(QString::fromLocal8Bit("醫(yī)生"));  

  16.     editor->addItem(QString::fromLocal8Bit("律師"));  

  17.     editor->addItem(QString::fromLocal8Bit("軍人"));  

  18.   

  19.     editor->installEventFilter(const_cast<ComboDelegate*>(this));  

  20.   

  21.     return editor;  

  22. }  

  23.   

  24. void ComboDelegate::setEditorData(QWidget *editor,  

  25.                                      const QModelIndex &index) const  

  26. {  

  27.     QString str = index.model()->data(index).toString();  

  28.       

  29.     QComboBox *box = static_cast<QComboBox*>(editor);  

  30.     int i = box->findText(str);  

  31.     box->setCurrentIndex(i);  

  32. }  

  33.   

  34. void ComboDelegate::setModelData(QWidget *editor, QAbstractItemModel *model,  

  35.                                     const QModelIndex &index) const  

  36. {  

  37.     QComboBox *box = static_cast<QComboBox*>(editor);  

  38.     QString str = box->currentText();  

  39.   

  40.     model->setData(index, str);  

  41. }  

  42.   

  43. void ComboDelegate::updateEditorGeometry(QWidget *editor,  

  44.     const QStyleOptionViewItem &option, const QModelIndex &/* index */const  

  45. {  

  46.     editor->setGeometry(option.rect);  

  47. }  


(3)插入微調(diào)器QSpinBox

[cpp] view plain copy

  1. #include "spindelegate.h"  

  2.   

  3. SpinDelegate::SpinDelegate(QObject *parent)  

  4.     : QItemDelegate(parent)  

  5. {  

  6. }  

  7.   

  8. QWidget *SpinDelegate::createEditor(QWidget *parent,  

  9.     const QStyleOptionViewItem &/* option */,  

  10.     const QModelIndex &/* index */const  

  11. {  

  12.     QSpinBox *editor = new QSpinBox(parent);  

  13.     editor->setRange(1000,10000);      

  14.   

  15.     editor->installEventFilter(const_cast<SpinDelegate*>(this));  

  16.   

  17.     return editor;  

  18. }  

  19.   

  20. void SpinDelegate::setEditorData(QWidget *editor,  

  21.                                      const QModelIndex &index) const  

  22. {  

  23.     int value = index.model()->data(index).toInt();  

  24.       

  25.     QSpinBox *spin = static_cast<QSpinBox*>(editor);  

  26.       

  27.     spin->setValue(value);  

  28. }  

  29.   

  30. void SpinDelegate::setModelData(QWidget *editor, QAbstractItemModel *model,  

  31.                                     const QModelIndex &index) const  

  32. {  

  33.     QSpinBox *spin = static_cast<QSpinBox*>(editor);  

  34.     int value = spin->value();  

  35.   

  36.     model->setData(index, value);  

  37. }  

  38.   

  39. void SpinDelegate::updateEditorGeometry(QWidget *editor,  

  40.     const QStyleOptionViewItem &option, const QModelIndex &/* index */const  

  41. {  

  42.     editor->setGeometry(option.rect);  

  43. }  


2、柱狀統(tǒng)計圖

自定義的View實現(xiàn)一個柱狀統(tǒng)計圖對TableModel的表格數(shù)據(jù)進行顯示。

[cpp] view plain copy

  1. #ifndef HISTOGRAMVIEW_H  

  2. #define HISTOGRAMVIEW_H  

  3.   

  4. #include <QtGui>  

  5.   

  6. class HistogramView : public QAbstractItemView  

  7. {  

  8.     Q_OBJECT  

  9. public:  

  10.     HistogramView(QWidget *parent=0);  

  11.       

  12.     QRect visualRect(const QModelIndex &index)const;  

  13.     void scrollTo(const QModelIndex &index, ScrollHint hint = EnsureVisible);  

  14.     QModelIndex indexAt(const QPoint &point) const;      

  15.       

  16.     void paintEvent(QPaintEvent *);  

  17.     void mousePressEvent(QMouseEvent *);  

  18.   

  19.     void setSelectionModel(QItemSelectionModel * selectionModel);  

  20.     QRegion itemRegion(QModelIndex index);    

  21.       

  22. protected slots:  

  23.     void dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight);  

  24.     void selectionChanged(const QItemSelection & selected, const QItemSelection & deselected );  

  25.       

  26. protected:  

  27.     QModelIndex moveCursor(QAbstractItemView::CursorAction cursorAction,  

  28.                             Qt::KeyboardModifiers modifiers);  

  29.     int horizontalOffset() const;  

  30.     int verticalOffset() const;      

  31.     bool isIndexHidden(const QModelIndex &index) const;  

  32.     void setSelection ( const QRect&rect, QItemSelectionModel::SelectionFlags flags );  

  33.     QRegion visualRegionForSelection(const QItemSelection &selection) const;         

  34.       

  35. private:  

  36.     QItemSelectionModel *selections;   

  37.       

  38.     QList<QRegion> listRegionM;    

  39.     QList<QRegion> listRegionF;   

  40.     QList<QRegion> listRegionS;   

  41.       

  42. };  

  43.   

  44. #endif   

[cpp] view plain copy

  1. #include "histogramview.h"  

  2.   

  3. HistogramView::HistogramView(QWidget *parent)  

  4.     : QAbstractItemView(parent)  

  5. {}  

  6.   

  7. void HistogramView::dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight)  

  8. {  

  9.     QAbstractItemView::dataChanged(topLeft, bottomRight);  

  10.       

  11.     viewport()->update();  

  12. }  

  13.   

  14. QRect HistogramView::visualRect(const QModelIndex &index) const  

  15. {}  

  16.   

  17. void HistogramView::scrollTo(const QModelIndex &index, ScrollHint hint)  

  18. {}  

  19.   

  20. QModelIndex HistogramView::indexAt(const QPoint &point) const  

  21. {  

  22.     QPoint newPoint(point.x(),point.y());  

  23.   

  24.     QRegion region;  

  25.     foreach(region,listRegionM)  

  26.     {  

  27.         if (region.contains(newPoint))  

  28.         {  

  29.             int row = listRegionM.indexOf(region);  

  30.             QModelIndex index = model()->index(row, 3,rootIndex());  

  31.             return index;  

  32.         }  

  33.     }  

  34.       

  35.     return QModelIndex();  

  36. }  

  37.   

  38. QModelIndex HistogramView::moveCursor(QAbstractItemView::CursorAction cursorAction,  

  39.                             Qt::KeyboardModifiers modifiers)  

  40. {}  

  41.                              

  42. int HistogramView::horizontalOffset() const  

  43. {  

  44. }  

  45.   

  46. int HistogramView::verticalOffset() const  

  47. {}  

  48.   

  49. bool HistogramView::isIndexHidden(const QModelIndex &index) const  

  50. {}  

  51.   

  52. void HistogramView::setSelectionModel(QItemSelectionModel * selectionModel)  

  53. {  

  54.     selections = selectionModel;  

  55. }  

  56.   

  57. void HistogramView::mousePressEvent(QMouseEvent *e)  

  58. {  

  59.     QAbstractItemView::mousePressEvent(e);  

  60.     setSelection(QRect(e->pos().x(),e->pos().y(),1,1),QItemSelectionModel::SelectCurrent);      

  61. }  

  62.       

  63. QRegion HistogramView::itemRegion(QModelIndex index)  

  64. {  

  65.     QRegion region;  

  66.   

  67.     if (index.column() == 3)  

  68.         region = listRegionM[index.row()];  

  69.   

  70.     return region;  

  71. }  

  72.   

  73. void HistogramView::setSelection ( const QRect &rect, QItemSelectionModel::SelectionFlags flags )  

  74. {  

  75.      int rows = model()->rowCount(rootIndex());  

  76.      int columns = model()->columnCount(rootIndex());  

  77.      QModelIndex selectedIndex;  

  78.   

  79.      for (int row = 0; row < rows; ++row)   

  80.      {  

  81.          for (int column = 1; column < columns; ++column)   

  82.          {  

  83.              QModelIndex index = model()->index(row, column, rootIndex());  

  84.              QRegion region = itemRegion(index);  

  85.            

  86.              if (!region.intersected(rect).isEmpty())  

  87.              selectedIndex = index;  

  88.          }  

  89.      }  

  90.        

  91.      if(selectedIndex.isValid())   

  92.          selections->select(selectedIndex,flags);  

  93.      else   

  94.      {  

  95.          QModelIndex noIndex;  

  96.          selections->select(noIndex, flags);  

  97.      }  

  98. }  

  99.   

  100. QRegion HistogramView::visualRegionForSelection(const QItemSelection &selection) const  

  101. {}  

  102.   

  103. void HistogramView::selectionChanged(const QItemSelection & selected, const QItemSelection & deselected )  

  104. {  

  105.     viewport()->update();  

  106. }  

  107.   

  108. void HistogramView::paintEvent(QPaintEvent *)  

  109. {  

  110.     QPainter painter(viewport());  

  111.   

  112.     painter.setPen(Qt::black);  

  113.     int x0 = 40;  

  114.     int y0 = 250;  

  115.       

  116.     // draw coordinate    

  117.     painter.drawLine(x0, y0, 40, 30);  

  118.     painter.drawLine(38, 32, 40, 30);  

  119.     painter.drawLine(40, 30, 42, 32);  

  120.     painter.drawText(5, 45, tr("income"));  

  121.       

  122.     for (int i=1; i<5; i++) {  

  123.         painter.drawLine(-1,-i*50,1,-i*50);  

  124.         painter.drawText(-20,-i*50,tr("%1").arg(i*5));  

  125.     }  

  126.   

  127.     // x軸  

  128.     painter.drawLine(x0, y0, 540, 250);  

  129.     painter.drawLine(538, 248, 540, 250);  

  130.     painter.drawLine(540, 250, 538, 252);  

  131.     painter.drawText(500, 270, tr("name"));  

  132.     int row;  

  133.     // name  

  134.     int posD = x0+20;  

  135.     for (row = 0; row < model()->rowCount(rootIndex()); row++)   

  136.     {  

  137.         QModelIndex index = model()->index(row, 0, rootIndex());  

  138.         QString dep = model()->data(index).toString();      

  139.           

  140.         painter.drawText(posD,y0+20,dep);  

  141.         posD += 50;  

  142.     }  

  143.     // income  

  144.     int posM = x0+20;  

  145.     for (row = 0; row < model()->rowCount(rootIndex()); row++)  

  146.     {  

  147.         QModelIndex index = model()->index(row, 3, rootIndex());  

  148.         int income = model()->data(index).toDouble();  

  149.   

  150.         int width = 10;  

  151.   

  152.         if (selections->isSelected(index))  

  153.             painter.setBrush(QBrush(Qt::darkBlue,Qt::SolidPattern));  

  154.         else  

  155.             painter.setBrush(Qt::blue);  

  156.   

  157.         painter.drawRect(QRectF(posM + 10, y0-income/25, width, income/25));  

  158.         QRegion regionM(posM + 10, y0-income/25, width, income/25);  

  159.         listRegionM << regionM;  

  160.   

  161.         posM += 50;  

  162.     }  

  163. }  

       分析:對父類的QAbstractItemView中的所有純虛函數(shù)都必須進行聲明,純虛函數(shù)包括visualRect()、scrollTo()、indexAt()、moveCursor()、horizontalOffset()、verticalOffset()、isIndexHidden()、setSelection()和visualRegionForSelection(),這些函數(shù)并不一定都要實現(xiàn),根據(jù)功能要求選擇實現(xiàn)。


向AI問一下細節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

qt %d
AI