生活随笔
收集整理的這篇文章主要介紹了
Qt学习: Model/View实现表格和统计图
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
博主QQ:1356438802
一、簡介
?????? Model/View結構使數據管理與相應的數據顯示相互獨立,并提供了一系列標準的函數接口和用于Model模塊與View模塊之間的通信。它從MVC演化而來,MVC由三種對象組成,Model是應用程序對象,View是它的屏幕表示,Controller定義了用戶界面如何對用戶輸入進行響應。把MVC中的View和Controller合在一起,就形成了Model/View結構。
二、運行圖
(1)為了靈活對用戶的輸入進行處理,引入了Delegate,Model、View、Delegate三個模塊之間通過信號與槽機制實現,當自身的狀態發生改變時會發出信號通知其他模塊。它們間的關系如下圖1所示。
?????? QAbstractItemModel是所有Model的基類,但一般不直接使用QAbstractItemModel,而是使用它的子類。Model模塊本身并不存儲數據,而是為View和Delegate訪問數據提供標準的接口。
???? ? View模塊從Model中獲得數據項顯示給用戶,Qt提供了一些常用的View模型,如QTreeView、QTableView和QListView。
?????? Delegate的基本接口在QAbstractItemDelegate類中定義,通過實現paint()和sizeHint()以達到渲染數據項的目的。
(2)程序運行圖如下圖2所示。
三、詳解
1、表格中嵌入控件
利用Delegate的方式實現表格中嵌入各種不同控件的效果,控件在需要編輯數據項時才出現。
(1)插入日歷編輯框QDateLineEdit
[cpp]? view plain
?copy #ifndef?DATEDELEGATE_H?? #define?DATEDELEGATE_H?? ?? #include?<QtGui>?? ?? class?DateDelegate?:?public?QItemDelegate?? {?? ????Q_OBJECT?? ?? public:?? ????DateDelegate(QObject?*parent?=?0);?? ?? ????QWidget?*createEditor(QWidget?*parent,?const?QStyleOptionViewItem?&option,?? ???????????????????????????const?QModelIndex?&index)?const;?? ?? ????void?setEditorData(QWidget?*editor,?const?QModelIndex?&index)?const;?? ????void?setModelData(QWidget?*editor,?QAbstractItemModel?*model,?? ???????????????????????const?QModelIndex?&index)?const;?? ?? ????void?updateEditorGeometry(QWidget?*editor,?? ?????????const?QStyleOptionViewItem?&option,?const?QModelIndex?&index)?const;?? };?? ?? #endif??
[cpp]? view plain
?copy #include?"datedelegate.h"?? ?? DateDelegate::DateDelegate(QObject?*parent)?? ????:?QItemDelegate(parent)?? {?? }?? ?? QWidget?*DateDelegate::createEditor(QWidget?*parent,?? ????const?QStyleOptionViewItem?&,?? ????const?QModelIndex?&)?const?? {?? ????QDateTimeEdit?*editor?=?new?QDateTimeEdit(parent);?? ????editor->setDisplayFormat("yyyy-MM-dd");?? ????editor->setCalendarPopup(true);?? ????editor->installEventFilter(const_cast<DateDelegate*>(this));?? ?? ????return?editor;?? }?? ?? void?DateDelegate::setEditorData(QWidget?*editor,?? ?????????????????????????????????????const?QModelIndex?&index)?const?? {?? ????QString?dateStr?=?index.model()->data(index).toString();?? ????QDate?date?=?QDate::fromString(dateStr,Qt::ISODate);?? ?? ????QDateTimeEdit?*edit?=?static_cast<QDateTimeEdit*>(editor);?? ????edit->setDate(date);?? }?? ?? void?DateDelegate::setModelData(QWidget?*editor,?QAbstractItemModel?*model,?? ????????????????????????????????????const?QModelIndex?&index)?const?? {?? ????QDateTimeEdit?*edit?=?static_cast<QDateTimeEdit*>(editor);?? ????QDate?date?=?edit->date();?? ?? ????model->setData(index,?QVariant(date.toString(Qt::ISODate)));?? }?? ?? void?DateDelegate::updateEditorGeometry(QWidget?*editor,?? ????const?QStyleOptionViewItem?&option,?const?QModelIndex?&)?const?? {?? ????editor->setGeometry(option.rect);?? }??
?????? 分析:DateDelegate繼承QItemDelegate,一般需要重定義聲明中的幾個虛函數。createEditor()函數完成創建控件的工作;setEditorDate()設置控件顯示的數據,把Model數據更新至Delegate,相當于初始化工作;setModelDate()把Delegate中對數據的更改更新至Model中;updateEditor()更析控件區的顯示。
(2)插入下拉列表框QComboBox
[cpp]? view plain
?copy #include?"combodelegate.h"?? ?? ComboDelegate::ComboDelegate(QObject?*parent)?? ????:?QItemDelegate(parent)?? {?? }?? ?? QWidget?*ComboDelegate::createEditor(QWidget?*parent,?? ????const?QStyleOptionViewItem?&,?? ????const?QModelIndex?&)?const?? {?? ????QComboBox?*editor?=?new?QComboBox(parent);?? ????editor->addItem(QString::fromLocal8Bit("工人"));?? ????editor->addItem(QString::fromLocal8Bit("農民"));?? ????editor->addItem(QString::fromLocal8Bit("醫生"));?? ????editor->addItem(QString::fromLocal8Bit("律師"));?? ????editor->addItem(QString::fromLocal8Bit("軍人"));?? ?? ????editor->installEventFilter(const_cast<ComboDelegate*>(this));?? ?? ????return?editor;?? }?? ?? void?ComboDelegate::setEditorData(QWidget?*editor,?? ?????????????????????????????????????const?QModelIndex?&index)?const?? {?? ????QString?str?=?index.model()->data(index).toString();?? ?????? ????QComboBox?*box?=?static_cast<QComboBox*>(editor);?? ????int?i?=?box->findText(str);?? ????box->setCurrentIndex(i);?? }?? ?? void?ComboDelegate::setModelData(QWidget?*editor,?QAbstractItemModel?*model,?? ????????????????????????????????????const?QModelIndex?&index)?const?? {?? ????QComboBox?*box?=?static_cast<QComboBox*>(editor);?? ????QString?str?=?box->currentText();?? ?? ????model->setData(index,?str);?? }?? ?? void?ComboDelegate::updateEditorGeometry(QWidget?*editor,?? ????const?QStyleOptionViewItem?&option,?const?QModelIndex?&)?const?? {?? ????editor->setGeometry(option.rect);?? }??
(3)插入微調器QSpinBox
[cpp]? view plain
?copy #include?"spindelegate.h"?? ?? SpinDelegate::SpinDelegate(QObject?*parent)?? ????:?QItemDelegate(parent)?? {?? }?? ?? QWidget?*SpinDelegate::createEditor(QWidget?*parent,?? ????const?QStyleOptionViewItem?&,?? ????const?QModelIndex?&)?const?? {?? ????QSpinBox?*editor?=?new?QSpinBox(parent);?? ????editor->setRange(1000,10000);?????? ?? ????editor->installEventFilter(const_cast<SpinDelegate*>(this));?? ?? ????return?editor;?? }?? ?? void?SpinDelegate::setEditorData(QWidget?*editor,?? ?????????????????????????????????????const?QModelIndex?&index)?const?? {?? ????int?value?=?index.model()->data(index).toInt();?? ?????? ????QSpinBox?*spin?=?static_cast<QSpinBox*>(editor);?? ?????? ????spin->setValue(value);?? }?? ?? void?SpinDelegate::setModelData(QWidget?*editor,?QAbstractItemModel?*model,?? ????????????????????????????????????const?QModelIndex?&index)?const?? {?? ????QSpinBox?*spin?=?static_cast<QSpinBox*>(editor);?? ????int?value?=?spin->value();?? ?? ????model->setData(index,?value);?? }?? ?? void?SpinDelegate::updateEditorGeometry(QWidget?*editor,?? ????const?QStyleOptionViewItem?&option,?const?QModelIndex?&)?const?? {?? ????editor->setGeometry(option.rect);?? }??
2、柱狀統計圖
自定義的View實現一個柱狀統計圖對TableModel的表格數據進行顯示。
[cpp]? view plain
?copy #ifndef?HISTOGRAMVIEW_H?? #define?HISTOGRAMVIEW_H?? ?? #include?<QtGui>?? ?? class?HistogramView?:?public?QAbstractItemView?? {?? ????Q_OBJECT?? public:?? ????HistogramView(QWidget?*parent=0);?? ?????? ????QRect?visualRect(const?QModelIndex?&index)const;?? ????void?scrollTo(const?QModelIndex?&index,?ScrollHint?hint?=?EnsureVisible);?? ????QModelIndex?indexAt(const?QPoint?&point)?const;?????? ?????? ????void?paintEvent(QPaintEvent?*);?? ????void?mousePressEvent(QMouseEvent?*);?? ?? ????void?setSelectionModel(QItemSelectionModel?*?selectionModel);?? ????QRegion?itemRegion(QModelIndex?index);???? ?????? protected?slots:?? ????void?dataChanged(const?QModelIndex?&topLeft,?const?QModelIndex?&bottomRight);?? ????void?selectionChanged(const?QItemSelection?&?selected,?const?QItemSelection?&?deselected?);?? ?????? protected:?? ????QModelIndex?moveCursor(QAbstractItemView::CursorAction?cursorAction,?? ????????????????????????????Qt::KeyboardModifiers?modifiers);?? ????int?horizontalOffset()?const;?? ????int?verticalOffset()?const;?????? ????bool?isIndexHidden(const?QModelIndex?&index)?const;?? ????void?setSelection?(?const?QRect&rect,?QItemSelectionModel::SelectionFlags?flags?);?? ????QRegion?visualRegionForSelection(const?QItemSelection?&selection)?const;????????? ?????? private:?? ????QItemSelectionModel?*selections;??? ?????? ????QList<QRegion>?listRegionM;???? ????QList<QRegion>?listRegionF;??? ????QList<QRegion>?listRegionS;??? ?????? };?? ?? #endif???
[cpp]? view plain
?copy #include?"histogramview.h"?? ?? HistogramView::HistogramView(QWidget?*parent)?? ????:?QAbstractItemView(parent)?? {}?? ?? void?HistogramView::dataChanged(const?QModelIndex?&topLeft,?const?QModelIndex?&bottomRight)?? {?? ????QAbstractItemView::dataChanged(topLeft,?bottomRight);?? ?????? ????viewport()->update();?? }?? ?? QRect?HistogramView::visualRect(const?QModelIndex?&index)?const?? {}?? ?? void?HistogramView::scrollTo(const?QModelIndex?&index,?ScrollHint?hint)?? {}?? ?? QModelIndex?HistogramView::indexAt(const?QPoint?&point)?const?? {?? ????QPoint?newPoint(point.x(),point.y());?? ?? ????QRegion?region;?? ????foreach(region,listRegionM)?? ????{?? ????????if?(region.contains(newPoint))?? ????????{?? ????????????int?row?=?listRegionM.indexOf(region);?? ????????????QModelIndex?index?=?model()->index(row,?3,rootIndex());?? ????????????return?index;?? ????????}?? ????}?? ?????? ????return?QModelIndex();?? }?? ?? QModelIndex?HistogramView::moveCursor(QAbstractItemView::CursorAction?cursorAction,?? ????????????????????????????Qt::KeyboardModifiers?modifiers)?? {}?? ????????????????????????????? int?HistogramView::horizontalOffset()?const?? {?? }?? ?? int?HistogramView::verticalOffset()?const?? {}?? ?? bool?HistogramView::isIndexHidden(const?QModelIndex?&index)?const?? {}?? ?? void?HistogramView::setSelectionModel(QItemSelectionModel?*?selectionModel)?? {?? ????selections?=?selectionModel;?? }?? ?? void?HistogramView::mousePressEvent(QMouseEvent?*e)?? {?? ????QAbstractItemView::mousePressEvent(e);?? ????setSelection(QRect(e->pos().x(),e->pos().y(),1,1),QItemSelectionModel::SelectCurrent);?????? }?? ?????? QRegion?HistogramView::itemRegion(QModelIndex?index)?? {?? ????QRegion?region;?? ?? ????if?(index.column()?==?3)?? ????????region?=?listRegionM[index.row()];?? ?? ????return?region;?? }?? ?? void?HistogramView::setSelection?(?const?QRect?&rect,?QItemSelectionModel::SelectionFlags?flags?)?? {?? ?????int?rows?=?model()->rowCount(rootIndex());?? ?????int?columns?=?model()->columnCount(rootIndex());?? ?????QModelIndex?selectedIndex;?? ?? ?????for?(int?row?=?0;?row?<?rows;?++row)??? ?????{?? ?????????for?(int?column?=?1;?column?<?columns;?++column)??? ?????????{?? ?????????????QModelIndex?index?=?model()->index(row,?column,?rootIndex());?? ?????????????QRegion?region?=?itemRegion(index);?? ??????????? ?????????????if?(!region.intersected(rect).isEmpty())?? ?????????????selectedIndex?=?index;?? ?????????}?? ?????}?? ??????? ?????if(selectedIndex.isValid())??? ?????????selections->select(selectedIndex,flags);?? ?????else??? ?????{?? ?????????QModelIndex?noIndex;?? ?????????selections->select(noIndex,?flags);?? ?????}?? }?? ?? QRegion?HistogramView::visualRegionForSelection(const?QItemSelection?&selection)?const?? {}?? ?? void?HistogramView::selectionChanged(const?QItemSelection?&?selected,?const?QItemSelection?&?deselected?)?? {?? ????viewport()->update();?? }?? ?? void?HistogramView::paintEvent(QPaintEvent?*)?? {?? ????QPainter?painter(viewport());?? ?? ????painter.setPen(Qt::black);?? ????int?x0?=?40;?? ????int?y0?=?250;?? ?????? ?????? ????painter.drawLine(x0,?y0,?40,?30);?? ????painter.drawLine(38,?32,?40,?30);?? ????painter.drawLine(40,?30,?42,?32);?? ????painter.drawText(5,?45,?tr("income"));?? ?????? ????for?(int?i=1;?i<5;?i++)?{?? ????????painter.drawLine(-1,-i*50,1,-i*50);?? ????????painter.drawText(-20,-i*50,tr("%1").arg(i*5));?? ????}?? ?? ?????? ????painter.drawLine(x0,?y0,?540,?250);?? ????painter.drawLine(538,?248,?540,?250);?? ????painter.drawLine(540,?250,?538,?252);?? ????painter.drawText(500,?270,?tr("name"));?? ????int?row;?? ?????? ????int?posD?=?x0+20;?? ????for?(row?=?0;?row?<?model()->rowCount(rootIndex());?row++)??? ????{?? ????????QModelIndex?index?=?model()->index(row,?0,?rootIndex());?? ????????QString?dep?=?model()->data(index).toString();?????? ?????????? ????????painter.drawText(posD,y0+20,dep);?? ????????posD?+=?50;?? ????}?? ?????? ????int?posM?=?x0+20;?? ????for?(row?=?0;?row?<?model()->rowCount(rootIndex());?row++)?? ????{?? ????????QModelIndex?index?=?model()->index(row,?3,?rootIndex());?? ????????int?income?=?model()->data(index).toDouble();?? ?? ????????int?width?=?10;?? ?? ????????if?(selections->isSelected(index))?? ????????????painter.setBrush(QBrush(Qt::darkBlue,Qt::SolidPattern));?? ????????else?? ????????????painter.setBrush(Qt::blue);?? ?? ????????painter.drawRect(QRectF(posM?+?10,?y0-income/25,?width,?income/25));?? ????????QRegion?regionM(posM?+?10,?y0-income/25,?width,?income/25);?? ????????listRegionM?<<?regionM;?? ?? ????????posM?+=?50;?? ????}?? }??
?????? 分析:對父類的QAbstractItemView中的所有純虛函數都必須進行聲明,
純虛函數
包括visualRect()、scrollTo()、indexAt()、moveCursor()、horizontalOffset()、verticalOffset()、isIndexHidden()、setSelection()和visualRegionForSelection(),這些函數并不一定都要實現,根據功能要求選擇實現。
四、總結
(1)Mode/View結構比較難于理解,在此先作簡單的介紹,以后再進行更加深入的研究。
(2)感興趣的可以下載源碼分析,并在其基礎上進行自己的開發,本人水平有限,也只能提供代碼供讀者延伸。
(3)源碼已經打包上傳到csdn上可登錄下載(http://download.csdn.net/detail/taiyang1987912/7797583)。??
(4)若有更好的設計建議,也可發郵件溝通,在此先感謝!郵箱地址yang.ao@i-soft.com.cn。
總結
以上是生活随笔為你收集整理的Qt学习: Model/View实现表格和统计图的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。