38.Qt模型/视图结构
Posted 喵小喵~
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了38.Qt模型/视图结构相关的知识,希望对你有一定的参考价值。
- 1.模型/视图类
- 2.模型
- 3.视图
- 4.代理
1 模型/视图类
InterView框架提供了一些可以直接使用的模型类和视图类,如QStandardModel类,QDirModel类,QStringListModel类,以及QColumnView类,QHeaderView类,QListView类,QTableView类和QTreeView类
简单目录浏览器:
1 #include "mainwindow.h" 2 #include <QApplication> 3 4 #include <QAbstractItemModel> 5 #include <QAbstractItemView> 6 #include <QItemSelectionModel> 7 8 #include <QDirModel> 9 #include <QTreeView> 10 #include <QListView> 11 #include <QTableView> 12 #include <QSplitter> 13 14 int main(int argc, char *argv[]) 15 { 16 QApplication a(argc, argv); 17 // MainWindow w 18 // w.show(); 19 20 //新建一个QDirModel对象,为数据访问做准备,QDirModel的创建还可以设置过滤器 21 //即只有符合条件的文件或目录才可被访问 22 //QDirModel类继承自QAbstractItemModel类,为访问本地系统提供数据模型,它提供了如 23 //新建,删除,创建目录等一系列与文件操作相关的函数 24 QDirModel model; 25 26 //新建三种不同的View对象,以便文件目录可以以三种不同的方式显示 27 QTreeView tree; 28 QListView list; 29 QTableView table; 30 31 //设置View对象的Model为QDirModel对象的model 32 tree.setModel(&model); 33 list.setModel(&model); 34 table.setModel(&model); 35 36 //设置QTreeView对象的选择方式为多选 37 //QAbstractItemView提供了五种选择模式,QAbstractItem View::SingleSelection. 38 //QAbstractItemView::NoSelection,QAbstractItemView::ContiguousSelection 39 //QAbstractItemView::ExtendedSelection和QAbstractItemView::MultiSelection 40 tree.setSelectionMode(QAbstractItemView::MultiSelection); 41 //设置QTableView对象与QTreeView对象使用相同的选择模型 42 list.setSelectionModel(tree.selectionModel()); 43 table.setSelectionMode(tree.selectionMode()); 44 45 //为了实现双击QTreeView对象中的某个目录时,QListView对象和QTableView对象显示此选定目录 46 //下的所有文件和目录,需要连接QTreeView对象的doubleClicked()信号与QListView对象的 47 //setRootIndex()槽函数 48 QObject::connect(&tree,SIGNAL(doubleClicked(QModelIndex)),&list, 49 SLOT(setRootIndex(QModelIndex))); 50 QObject::connect(&tree,SIGNAL(doubleClicked(QModelIndex)),&table, 51 SLOT(setRootIndex(QModelIndex))); 52 53 QSplitter *splitter = new QSplitter; 54 splitter->addWidget(&tree); 55 splitter->addWidget(&list); 56 splitter->addWidget(&table); 57 splitter->setWindowTitle(QObject::tr("Model/view")); 58 splitter->show(); 59 60 return a.exec(); 61 }
2 模型
实现自定义模型可以通过QAbstractItemModel类继承,也可以通过QAbstractListModel和QAbstractTableModel类继承实现列表模型或表格模型;
代码示例:
- modelx.h
1 #ifndef MODELEX_H 2 #define MODELEX_H 3 4 #include <QAbstractTableModel> 5 #include <QVector> 6 #include <QMap> 7 #include <QStringList> 8 #include <QObject> 9 10 class modelex:public QAbstractTableModel 11 { 12 public: 13 explicit modelex(QObject *parent=0); 14 15 virtual int rowCount(const QModelIndex &parent=QModelIndex()) const; 16 virtual int columnCount(const QModelIndex &parent=QModelIndex()) const; 17 18 QVariant data(const QModelIndex &index, int role) const; 19 //返回表头的函数 20 QVariant headerData(int section,Qt::Orientation orientation,int role)const; 21 22 private: 23 QVector<short> army; 24 QVector<short> weaponType; 25 26 //数值-文字映射 27 QMap<short,QString> armyMap; 28 QMap<short,QString> weaponTypeMap; 29 30 QStringList weapon; 31 QStringList header; 32 33 //完成表格数据的初始化填充 34 void populateModel(); 35 }; 36 37 #endif // MODELEX_H
- modelx.cpp
1 #include "modelex.h" 2 #include "modelex.h" 3 modelex::modelex(QObject *parent): 4 QAbstractTableModel(parent) 5 { 6 //创建映射 7 armyMap[1]=tr("空军"); 8 armyMap[2]=tr("海军"); 9 armyMap[3]=tr("陆军"); 10 armyMap[4]=tr("海军陆战队"); 11 12 weaponTypeMap[1]=tr("轰炸机"); 13 weaponTypeMap[2]=tr("战斗机"); 14 weaponTypeMap[3]=tr("航空母舰"); 15 weaponTypeMap[4]=tr("驱逐舰"); 16 weaponTypeMap[5]=tr("直升机"); 17 weaponTypeMap[6]=tr("坦克"); 18 weaponTypeMap[7]=tr("两栖攻击舰"); 19 weaponTypeMap[8]=tr("两栖战车"); 20 21 //绘制模型 22 populateModel(); 23 } 24 25 26 27 //获取模型的行数 28 int modelex::rowCount(const QModelIndex &parent) const 29 { 30 return army.size(); 31 } 32 33 //返回模型的列数 34 int modelex::columnCount(const QModelIndex &parent) const 35 { 36 return 4; 37 } 38 39 //返回指定索引的数据,即将数值映射为文字 40 //循环把模型的每行每列给绘制了(函数名不能换成其他名字) 41 QVariant modelex::data(const QModelIndex &index, int role) const 42 { 43 if(!index.isValid()) 44 { 45 return QVariant(); 46 } 47 48 //模型中的条目可以有不同个角色,这样就可以在不同的情况下提供不同的数据. 49 //如,Qt::DisplayRole用来存取视图中显示的文字,角色由枚举类Qt::ItemDataRole定义 50 //Qt::DisplayRole 显示文字 51 //Qt::DecorationRole 绘制装饰数据(通常是图标) 52 //Qt::EditRole 在编辑器中编辑的数据 53 //Qt::ToolTipRole 工具提示 54 //Qt::StatusTipRole 状态栏提示 55 //Qt::WhatsThisRole What\'s This文字 56 //Qt::SizeHintRole 尺寸提示 57 //Qt::FontRole 默认代理的绘制使用的字体 58 //Qt::TextAlignmentRole 默认代理的对齐方式 59 //Qt::BackgroundRole 默认代理的背景画刷 60 //Qt::ForegroundRole 默认代理的前景画刷 61 //Qt::CheckStateRole 默认代理的检查框状态 62 //Qt::UserRole 用户自定义的数据的起始位置 63 if(role==Qt::DisplayRole) 64 { 65 //遍历没一列 66 switch(index.column()) 67 { 68 case 0: 69 //当前行数对应的军队 70 return armyMap[army[index.row()]]; 71 break; 72 case 1: 73 //当前行数对应的类型,以及此类型对应的武器种类 74 return weaponTypeMap[weaponType[index.row()]]; 75 case 2: 76 //当前行数对应的武器 77 return weapon[ index.row() ]; 78 default: 79 return QVariant(); 80 } 81 } 82 return QVariant(); 83 } 84 85 //返回固定的表头数据,设置水平表头的标题(内部循环实现) 86 QVariant modelex::headerData(int section, Qt::Orientation orientation, int role) const 87 { 88 if(role==Qt::DisplayRole&&orientation==Qt::Horizontal) 89 return header[section]; 90 91 return QAbstractTableModel::headerData(section,orientation,role); 92 } 93 94 //绘制 95 void modelex::populateModel() 96 { 97 //表头 98 header<<tr("军种")<<tr("武器种类")<<tr("武器")<<tr("测试"); 99 //军队 100 army<<1<<2<<3<<4<<2<<4<<3<<1; 101 //武器种类 102 weaponType<<1<<3<<5<<7<<4<<8<<6<<3; 103 //武器 104 weapon<<tr("B-2")<<tr("尼米兹级")<<tr("黄蜂级")<<tr("阿利伯克级") 105 <<tr("阿帕奇")<<tr("AAAV")<<tr("M1A1")<<tr("F-22"); 106 }
- main.cpp
1 #include <QApplication> 2 3 #include "modelex.h" 4 #include <QTableView> 5 6 int main(int argc, char *argv[]) 7 { 8 QApplication a(argc, argv); 9 10 modelex modleEx; 11 QTableView view; 12 view.setModel(&modleEx); 13 view.setWindowTitle(QObject::tr("模型示例")); 14 view.resize(400,400); 15 view.show(); 16 return a.exec(); 17 }
3 视图
实现自定义的View,可继承自QAbstractItemView类,对所需的纯虚函数进行重定义与实现,对于QAbstractItemView类中的纯虚函数,在子类必须进行重定义,但不一定要实现,可根据需要选择实现.
- histogramview.h
1 #ifndef HISTOGRAMVIEW_H 2 #define HISTOGRAMVIEW_H 3 #include <QAbstractItemView> 4 #include <QItemSelectionModel> 5 #include <QRegion> 6 #include <QMouseEvent> 7 8 9 10 class HistogramView : public QAbstractItemView 11 { 12 public: 13 HistogramView(QWidget *parent); 14 15 //14-17 一定要声明 16 QRect visualRect(const QModelIndex &index) const; 17 void scrollTo(const QModelIndex &index, ScrollHint hint=EnsureVisible); 18 //当鼠标处在某个数据项的区域中,则返回此数据项的Index值,否则返回一个空的Index 19 QModelIndex indexAt(const QPoint &point) const; 20 21 22 //为selections赋初值 23 void setSelectionModel(QItemSelectionModel *selectionModel); 24 QRegion itemRegion(QModelIndex index); 25 26 //完成柱状统计图的绘制 27 void paintEvent(QPaintEvent *); 28 //柱状统计图可以被鼠标单击选择,选中后以不同的方式显示 29 void mousePressEvent(QMouseEvent *event); 30 31 protected slots: 32 //当数据项选择发生变化时此槽函数将响应 33 void selectionChanged(const QItemSelection &selected, 34 const QItemSelection &deselected); 35 //当模型中的数据发生变更时,此槽函数将响应 36 void dataChanged(const QModelIndex &topLeft, 37 const QModelIndex &bottomRight); 38 39 protected: 40 //39-48 一定要声明 41 QModelIndex moveCursor(CursorAction cursorAction, Qt::KeyboardModifiers modifiers); 42 int horizontalOffset() const; 43 int verticalOffset() const; 44 bool isIndexHidden(const QModelIndex &index) const; 45 //将位于QRect内的数据项按照SelectionFlags(描述被选择的数据项以何种方式进行更新) 46 //指定的方式进行更新.QItemSelectionModel类提供多种可用的SelectionFlags,常用的有 47 //QItemSelectionModel::Select,QItemSelectionModel::Current等 48 void setSelection(const QRect &rect, QItemSelectionModel::SelectionFlags flags); 49 QRegion visualRegionForSelection(const QItemSelection &selection) const; 50 51 private: 52 //用于保存与视图选项相关的内容 53 QItemSelectionModel *selections; 54 //用于保存其中某一类型柱状图区域范围,而每个区域是QList中的一个值 55 QList<QRegion> MRegionList; 56 QList<QRegion> FRegionList; 57 QList<QRegion> SRegionList; 58 59 60 }; 61 62 #endif // HISTOGRAMVIEW_H
- histogramview.cpp
1 #include "histogramview.h" 2 3 #include <QPainter> 4 5 6 //当鼠标处在某个数据项的区域中,则返回此数据项的Index值,否则返回一个空的Index 7 QModelIndex HistogramView::indexAt(const QPoint &point) const 8 { 9 QPoint newPoint(point.x(),point.y()); 10 QRegion region; 11 //检查当前点是否处于第一列(男)数据的区域中 12 foreach(region,MRegionList)//男列 13 { 14 if(region.contains(newPoint)) 15 { 16 int row = MRegionList.indexOf(region); 17 QModelIndex index = model()->index(row,1,rootIndex()); 18 return index; 19 } 20 } 21 22 //检查当前点是否处于第二列(女)数据的区域中 23 foreach(region,FRegionList)//女列 24 { 25 if(region.contains(newPoint)) 26 { 27 int row = FRegionList.indexOf(region); 28 QModelIndex index = model()->index(row,2,rootIndex()); 29 return index; 30 } 31 } 32 33 //检查当前点是否处于第三列(合计)数据的区域中 34 foreach(region,SRegionList) //合计 列 35 { 36 if(region.contains(newPoint)) 37 { 38 int row=SRegionList.indexOf(region); 39 QModelIndex index = model()->index(row,3,rootIndex()); 40 return index; 41 } 42 } 43 return QModelIndex(); 44 } 45 46 //为selections赋初值 47 void HistogramView::setSelectionModel(QItemSelectionModel *selectionModel) 48 { 49 selections=selectionModel; 50 } 51 52 53 QRegion HistogramView::itemRegion(QModelIndex index) 54 { 55 QRegion region; 56 if(index.column()==1) //男 57 region = MRegionList[index.row()]; 58 if(index.column()==2) //女 59 region = FRegionList[index.row()]; 60 if(index.column()==3) //退休 61 region = SRegionList[index.row()]; 62 63 return region; 64 } 65 66 //完成柱状统计图的绘制 67 void HistogramView::paintEvent(QPaintEvent *) 68 { 69 //以viewport()作为绘图设备新建一个QPainter对象 70 QPainter painter(viewport()); 71 painter.setPen(Qt::black); 72 73 int x0=40; 74 int y0=250; 75 76 //20-46行完成了x,y坐标轴的绘制,并标注坐标轴的变量 77 //y坐标轴 78 painter.drawLine(x0,y0,40,30); 79 //箭头绘制 80 painter.drawLine(38,32,40,30); 81 painter.drawLine(40,30,42,32); 82 83 painter.drawText(20,30,tr("人数")); 84 //绘制坐标 85 for(int i=0;i<5;i++) 86 { 87 painter.drawLine(1,i*50,1,i*50); 88 painter.drawText(20,i*50,tr("%1").arg((5-i)*5)); 89 } 90 //x坐标轴 91 painter.drawLine(x0,y0,540,250); 92 painter.drawLine(538,248,540,250); 93 painter.drawLine(540,250,538,252); 94 painter.drawText(545,250,tr("部门")); 95 96 int posD=x0+20; 如何防止在背面片段导航上再次设置视图模型