QT MVC 技术Model/View初探

Model/View实现表格技术

[+]

一、简介

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

  1. #ifndef DATEDELEGATE_H
  2. #define DATEDELEGATE_H
  3. #include <QtGui>
  4. class DateDelegate : public QItemDelegate
  5. {
  6. Q_OBJECT
  7. public:
  8. DateDelegate(QObject *parent = 0);
  9. QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option,
  10. const QModelIndex &index) const;
  11. void setEditorData(QWidget *editor, const QModelIndex &index) const;
  12. void setModelData(QWidget *editor, QAbstractItemModel *model,
  13. const QModelIndex &index) const;
  14. void updateEditorGeometry(QWidget *editor,
  15. const QStyleOptionViewItem &option, const QModelIndex &index) const;
  16. };
  17. #endif

[cpp] view plain copy

  1. #include "datedelegate.h"
  2. DateDelegate::DateDelegate(QObject *parent)
  3. : QItemDelegate(parent)
  4. {
  5. }
  6. QWidget *DateDelegate::createEditor(QWidget *parent,
  7. const QStyleOptionViewItem &/* option */,
  8. const QModelIndex &/* index */) const
  9. {
  10. QDateTimeEdit *editor = new QDateTimeEdit(parent);
  11. editor->setDisplayFormat("yyyy-MM-dd");
  12. editor->setCalendarPopup(true);
  13. editor->installEventFilter(const_cast<DateDelegate*>(this));
  14. return editor;
  15. }
  16. void DateDelegate::setEditorData(QWidget *editor,
  17. const QModelIndex &index) const
  18. {
  19. QString dateStr = index.model()->data(index).toString();
  20. QDate date = QDate::fromString(dateStr,Qt::ISODate);
  21. QDateTimeEdit *edit = static_cast<QDateTimeEdit*>(editor);
  22. edit->setDate(date);
  23. }
  24. void DateDelegate::setModelData(QWidget *editor, QAbstractItemModel *model,
  25. const QModelIndex &index) const
  26. {
  27. QDateTimeEdit *edit = static_cast<QDateTimeEdit*>(editor);
  28. QDate date = edit->date();
  29. model->setData(index, QVariant(date.toString(Qt::ISODate)));
  30. }
  31. void DateDelegate::updateEditorGeometry(QWidget *editor,
  32. const QStyleOptionViewItem &option, const QModelIndex &/* index */) const
  33. {
  34. editor->setGeometry(option.rect);
  35. }

分析:DateDelegate继承QItemDelegate,一般需要重定义声明中的几个虚函数。createEditor()函数完成创建控件的工作;setEditorDate()设置控件显示的数据,把Model数据更新至Delegate,相当于初始化工作;setModelDate()把Delegate中对数据的更改更新至Model中;updateEditor()更析控件区的显示。

(2)插入下拉列表框QComboBox

[cpp] view plain copy

  1. #include "combodelegate.h"
  2. ComboDelegate::ComboDelegate(QObject *parent)
  3. : QItemDelegate(parent)
  4. {
  5. }
  6. QWidget *ComboDelegate::createEditor(QWidget *parent,
  7. const QStyleOptionViewItem &/* option */,
  8. const QModelIndex &/* index */) const
  9. {
  10. QComboBox *editor = new QComboBox(parent);
  11. editor->addItem(QString::fromLocal8Bit("工人"));
  12. editor->addItem(QString::fromLocal8Bit("农民"));
  13. editor->addItem(QString::fromLocal8Bit("医生"));
  14. editor->addItem(QString::fromLocal8Bit("律师"));
  15. editor->addItem(QString::fromLocal8Bit("军人"));
  16. editor->installEventFilter(const_cast<ComboDelegate*>(this));
  17. return editor;
  18. }
  19. void ComboDelegate::setEditorData(QWidget *editor,
  20. const QModelIndex &index) const
  21. {
  22. QString str = index.model()->data(index).toString();
  23. QComboBox *box = static_cast<QComboBox*>(editor);
  24. int i = box->findText(str);
  25. box->setCurrentIndex(i);
  26. }
  27. void ComboDelegate::setModelData(QWidget *editor, QAbstractItemModel *model,
  28. const QModelIndex &index) const
  29. {
  30. QComboBox *box = static_cast<QComboBox*>(editor);
  31. QString str = box->currentText();
  32. model->setData(index, str);
  33. }
  34. void ComboDelegate::updateEditorGeometry(QWidget *editor,
  35. const QStyleOptionViewItem &option, const QModelIndex &/* index */) const
  36. {
  37. editor->setGeometry(option.rect);
  38. }

(3)插入微调器QSpinBox

[cpp] view plain copy

  1. #include "spindelegate.h"
  2. SpinDelegate::SpinDelegate(QObject *parent)
  3. : QItemDelegate(parent)
  4. {
  5. }
  6. QWidget *SpinDelegate::createEditor(QWidget *parent,
  7. const QStyleOptionViewItem &/* option */,
  8. const QModelIndex &/* index */) const
  9. {
  10. QSpinBox *editor = new QSpinBox(parent);
  11. editor->setRange(1000,10000);
  12. editor->installEventFilter(const_cast<SpinDelegate*>(this));
  13. return editor;
  14. }
  15. void SpinDelegate::setEditorData(QWidget *editor,
  16. const QModelIndex &index) const
  17. {
  18. int value = index.model()->data(index).toInt();
  19. QSpinBox *spin = static_cast<QSpinBox*>(editor);
  20. spin->setValue(value);
  21. }
  22. void SpinDelegate::setModelData(QWidget *editor, QAbstractItemModel *model,
  23. const QModelIndex &index) const
  24. {
  25. QSpinBox *spin = static_cast<QSpinBox*>(editor);
  26. int value = spin->value();
  27. model->setData(index, value);
  28. }
  29. void SpinDelegate::updateEditorGeometry(QWidget *editor,
  30. const QStyleOptionViewItem &option, const QModelIndex &/* index */) const
  31. {
  32. editor->setGeometry(option.rect);
  33. }

2、柱状统计图

自定义的View实现一个柱状统计图对TableModel的表格数据进行显示。

[cpp] view plain copy

  1. #ifndef HISTOGRAMVIEW_H
  2. #define HISTOGRAMVIEW_H
  3. #include <QtGui>
  4. class HistogramView : public QAbstractItemView
  5. {
  6. Q_OBJECT
  7. public:
  8. HistogramView(QWidget *parent=0);
  9. QRect visualRect(const QModelIndex &index)const;
  10. void scrollTo(const QModelIndex &index, ScrollHint hint = EnsureVisible);
  11. QModelIndex indexAt(const QPoint &point) const;
  12. void paintEvent(QPaintEvent *);
  13. void mousePressEvent(QMouseEvent *);
  14. void setSelectionModel(QItemSelectionModel * selectionModel);
  15. QRegion itemRegion(QModelIndex index);
  16. protected slots:
  17. void dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight);
  18. void selectionChanged(const QItemSelection & selected, const QItemSelection & deselected );
  19. protected:
  20. QModelIndex moveCursor(QAbstractItemView::CursorAction cursorAction,
  21. Qt::KeyboardModifiers modifiers);
  22. int horizontalOffset() const;
  23. int verticalOffset() const;
  24. bool isIndexHidden(const QModelIndex &index) const;
  25. void setSelection ( const QRect&rect, QItemSelectionModel::SelectionFlags flags );
  26. QRegion visualRegionForSelection(const QItemSelection &selection) const;
  27. private:
  28. QItemSelectionModel *selections;
  29. QList<QRegion> listRegionM;
  30. QList<QRegion> listRegionF;
  31. QList<QRegion> listRegionS;
  32. };
  33. #endif

[cpp] view plain copy

  1. #include "histogramview.h"
  2. HistogramView::HistogramView(QWidget *parent)
  3. : QAbstractItemView(parent)
  4. {}
  5. void HistogramView::dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight)
  6. {
  7. QAbstractItemView::dataChanged(topLeft, bottomRight);
  8. viewport()->update();
  9. }
  10. QRect HistogramView::visualRect(const QModelIndex &index) const
  11. {}
  12. void HistogramView::scrollTo(const QModelIndex &index, ScrollHint hint)
  13. {}
  14. QModelIndex HistogramView::indexAt(const QPoint &point) const
  15. {
  16. QPoint newPoint(point.x(),point.y());
  17. QRegion region;
  18. foreach(region,listRegionM)
  19. {
  20. if (region.contains(newPoint))
  21. {
  22. int row = listRegionM.indexOf(region);
  23. QModelIndex index = model()->index(row, 3,rootIndex());
  24. return index;
  25. }
  26. }
  27. return QModelIndex();
  28. }
  29. QModelIndex HistogramView::moveCursor(QAbstractItemView::CursorAction cursorAction,
  30. Qt::KeyboardModifiers modifiers)
  31. {}
  32. int HistogramView::horizontalOffset() const
  33. {
  34. }
  35. int HistogramView::verticalOffset() const
  36. {}
  37. bool HistogramView::isIndexHidden(const QModelIndex &index) const
  38. {}
  39. void HistogramView::setSelectionModel(QItemSelectionModel * selectionModel)
  40. {
  41. selections = selectionModel;
  42. }
  43. void HistogramView::mousePressEvent(QMouseEvent *e)
  44. {
  45. QAbstractItemView::mousePressEvent(e);
  46. setSelection(QRect(e->pos().x(),e->pos().y(),1,1),QItemSelectionModel::SelectCurrent);
  47. }
  48. QRegion HistogramView::itemRegion(QModelIndex index)
  49. {
  50. QRegion region;
  51. if (index.column() == 3)
  52. region = listRegionM[index.row()];
  53. return region;
  54. }
  55. void HistogramView::setSelection ( const QRect &rect, QItemSelectionModel::SelectionFlags flags )
  56. {
  57. int rows = model()->rowCount(rootIndex());
  58. int columns = model()->columnCount(rootIndex());
  59. QModelIndex selectedIndex;
  60. for (int row = 0; row < rows; ++row)
  61. {
  62. for (int column = 1; column < columns; ++column)
  63. {
  64. QModelIndex index = model()->index(row, column, rootIndex());
  65. QRegion region = itemRegion(index);
  66. if (!region.intersected(rect).isEmpty())
  67. selectedIndex = index;
  68. }
  69. }
  70. if(selectedIndex.isValid())
  71. selections->select(selectedIndex,flags);
  72. else
  73. {
  74. QModelIndex noIndex;
  75. selections->select(noIndex, flags);
  76. }
  77. }
  78. QRegion HistogramView::visualRegionForSelection(const QItemSelection &selection) const
  79. {}
  80. void HistogramView::selectionChanged(const QItemSelection & selected, const QItemSelection & deselected )
  81. {
  82. viewport()->update();
  83. }
  84. void HistogramView::paintEvent(QPaintEvent *)
  85. {
  86. QPainter painter(viewport());
  87. painter.setPen(Qt::black);
  88. int x0 = 40;
  89. int y0 = 250;
  90. // draw coordinate
  91. painter.drawLine(x0, y0, 40, 30);
  92. painter.drawLine(38, 32, 40, 30);
  93. painter.drawLine(40, 30, 42, 32);
  94. painter.drawText(5, 45, tr("income"));
  95. for (int i=1; i<5; i++) {
  96. painter.drawLine(-1,-i*50,1,-i*50);
  97. painter.drawText(-20,-i*50,tr("%1").arg(i*5));
  98. }
  99. // x轴
  100. painter.drawLine(x0, y0, 540, 250);
  101. painter.drawLine(538, 248, 540, 250);
  102. painter.drawLine(540, 250, 538, 252);
  103. painter.drawText(500, 270, tr("name"));
  104. int row;
  105. // name
  106. int posD = x0+20;
  107. for (row = 0; row < model()->rowCount(rootIndex()); row++)
  108. {
  109. QModelIndex index = model()->index(row, 0, rootIndex());
  110. QString dep = model()->data(index).toString();
  111. painter.drawText(posD,y0+20,dep);
  112. posD += 50;
  113. }
  114. // income
  115. int posM = x0+20;
  116. for (row = 0; row < model()->rowCount(rootIndex()); row++)
  117. {
  118. QModelIndex index = model()->index(row, 3, rootIndex());
  119. int income = model()->data(index).toDouble();
  120. int width = 10;
  121. if (selections->isSelected(index))
  122. painter.setBrush(QBrush(Qt::darkBlue,Qt::SolidPattern));
  123. else
  124. painter.setBrush(Qt::blue);
  125. painter.drawRect(QRectF(posM + 10, y0-income/25, width, income/25));
  126. QRegion regionM(posM + 10, y0-income/25, width, income/25);
  127. listRegionM << regionM;
  128. posM += 50;
  129. }
  130. }

分析:对父类的QAbstractItemView中的所有纯虚函数都必须进行声明,纯虚函数包括visualRect()、scrollTo()、indexAt()、moveCursor()、horizontalOffset()、verticalOffset()、isIndexHidden()、setSelection()和visualRegionForSelection(),这些函数并不一定都要实现,根据功能要求选择实现。

时间: 2024-12-26 15:24:22

QT MVC 技术Model/View初探的相关文章

Qt表格之Model/View实现

很多开发中都用到了表格,如何使用Qt做表格?比较简单的,我们可以使用QTableWidget,但是它有个问题,就是数据量不能太大,一旦数据量比较大的话就会带来内存问题.Qt还给我们提供了一样利器--Model/View.模型视图,接触Qt的都不会陌生,对新手来说可能不太好理解,没关系,Qt提供了强大的Assist文档和更加直观的Demo,相信看过之后使用来说就没有问题了.本篇文章来列出一个简单的例子,使用的就是表格的模型视图,在代码中给出了简单的注释说明.为什么要采用这种方式?试过的人都可以看到

Qt Model/View(转)

介绍 Qt 4推出了一组新的item view类,它们使用model/view结构来管理数据与表示层的关系.这种结构带来的功能上的分离给了开发人员更大的弹性来定制数据项的表示,它也提 供一个标准的model接口,使得更多的数据源可以被这些item view使用.这里对model/view的结构进行了描述,结构中的每个组件都进行了解释,给出了一些例子说明了提供的这些类如何使用. Model/View 结构 Model-View-Controller(MVC), 是从Smalltalk发展而来的一种

5.Qt model view设计模式

Introduction to Model/View Programming QT4 介绍了一系列新的 Item View 类,这些类使用Model/View结构来管理数据和数据如何呈现给用户.这种结构使程序员更加灵活的开发和定制呈现数据界面,Model/View结构提供标准的Model接口让各种数据资源都能够被存在的Item View使用. The model/view architecture MVC是一种源于 smalltalk的设计模式,经常用来构建应用程序界面. MVC有3个对象构成.

QT开发(三十八)——Model/View框架编程

QT开发(三十八)--Model/View框架编程 一.自定义模型 1.自定义只读模型 QAbstractItemModel为自定义模型提供了一个足够灵活的接口,能够支持数据源的层次结构,能够对数据进行增删改操作,还能够支持拖放.QT提供了 QAbstarctListModel和QAbstractTableModel两个类来简化非层次数据模型的开发,适合于结合列表和表格使用. 自定义模型需要考虑模型管理的的数据结构适合的视图的显示方式.如果模型的数据仅仅用于列表或表格的显示,那么可以使用QAbs

qt model/view 架构基础介绍之QListWidget

# -*- coding: utf-8 -*- # python:2.x __author__ = 'Administrator' from PyQt4.QtGui import  * from PyQt4.Qt import * from PyQt4 import QtGui, QtCore from PyQt4.QtCore import * import sys # MVC是Model-View-Controller的简写,即模型-视图-控制器 #model/view框架将传统的mv模型分

Qt的Model/View Framework解析(数据是从真正的“肉(raw)”里取得,Model提供肉,所以读写文件、操作数据库、网络通讯等一系列与数据打交道的工作就在model中做了)

最近在看Qt的Model/View Framework,在网上搜了搜,好像中文的除了几篇翻译没有什么有价值的文章.E文的除了Qt的官方介绍,其它文章也很少.看到一个老外在blog中写道Model/View是他认为Qt中最不好的一部分了.真的是这样吗?为了回馈开源社区,我写了这篇blog,写的是我认为比较有价值的东东.题目起得是解析,但也没有特别细节的介绍,点到为止,有兴趣的Tx可以继续讨论.我所看的资料有<C++ GUI Programming with Qt 4, Second Edition

QT Model View Controller 使用和认识

MVC全称是 Model View Controller,是一种非常非常流行的架构模式,相关MVC具体的,网上已经非常非常详尽了,不赘述了. 关于Qt中的MVC 其实Qt中的MVC并不叫MVC,而是叫"MVD",Qt中没有Controller的说法,而是使用了另外一种抽象: Delegate (委托) ,其行为和传统的MVC是相同的.写过C#的同学肯定对delegate就不陌生了,这里delegate的用法就是负责协调Model和View之间的数据.其思想如下图所示: Model是唯一

Qt Model/View( 一)

http://doc.trolltech.com/main-snapshot/model-view-programming.html 介绍 Qt 4推出了一组新的item view类,它们使用model/view结构来管理数据与表示层的关系.这种结构带来的功能上的分离给了开发人员更大的弹性来定制数据项的表示,它也提供一个标准的model接口,使得更多的数据源可以被这些item view使用.这里对model/view的结构进行了描述,结构中的每个组件都进行了解释,给出了一些例子说明了提供的这些类

qt model/view 架构自定义模型之QStringListModel

# -*- coding: utf-8 -*- # python:2.x #QStringListModel #QStringListModel 是最简单的模型类,具备向视图提供字符串数据的能力. #QStringListModel 是一个可编辑的模型,可以为组件提供一系列字符串作为数据. #看作是封装了 QStringList 的模型.QStringList 是一种很常用的数据类型,实际上 #是一个字符串列表(也就是 QList<QString>).既然是列表,它也就是线性的数据结构, #因