实现自定义的View,可继承自QAbstractItemView类,对所需的纯虚函数进行重定义与实现,对于QAbstractItemView类中的纯虚函数,在子类中必须进行重定义,但不一定要实现,可根据需要选择实现。

DEMO

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H#include <QMainWindow>
#include <QStandardItem>
#include <QTableView>
#include <QMenuBar>
#include <QMenu>
#include <QAction>
#include <QSplitter>
#include "histogramview.h"class MainWindow : public QMainWindow
{Q_OBJECTpublic:MainWindow(QWidget *parent = 0);~MainWindow();void creatAction();void creatMenu();void setupModel();void setupView();void openFile(QString);
public slots:void slotOpen();
private:QMenu *fileMenu;QAction *openAct;QStandardItemModel *model;QTableView *table;QSplitter *splitter;HistogramView *histogram;
};#endif // MAINWINDOW_H

histogramview.h

#ifndef HISTOGRAMVIEW_H
#define HISTOGRAMVIEW_H#include <QAbstractItemView>
#include <QItemSelectionModel>
#include <QRegion>
#include <QMouseEvent>
#include <QList>//自定义HistogramView类继承自QAbstractItemView类,用于对表格数据进行柱状图显示
class HistogramView:public QAbstractItemView
{Q_OBJECT
public:HistogramView(QWidget *parent=0);//虚函数的声明//QAbstractItemView类中的纯虚函数,这些纯虚函数不一定要实现,可以根据//需要选择性的实现,但一定要声明QRect visualRect(const QModelIndex &index) const;void scrollTo(const QModelIndex &index,ScrollHint hint=EnsureVisible);//当鼠标在视图中单击或位置发生改变时触发,它返回鼠标所在点的QModelIndex值,若鼠标//处在某个数据项的区域中,则返回此数据的Index值,否则返回一个空的IndexQModelIndex indexAt(const QPoint &point) const;//为selections赋初值void setSelectionModel(QItemSelectionModel *selectionModel);QRegion itemRegion(QModelIndex index);void paintEvent(QPaintEvent *);//柱状统计图可以被鼠标单击选择,选中后以不同的方式显现void mousePressEvent(QMouseEvent *event);
protected slots://当数据项发生改变时,此槽函数将响应void selectionChanged(const QItemSelection &selected,const QItemSelection &deselected);//当模型中的数据发生变更时,此槽函数响应void dataChanged(const QModelIndex &topLeft,const QModelIndex &bottomRight);
protected://虚函数声明QModelIndex moveCursor(QAbstractItemView::CursorAction cursorAction,Qt::KeyboardModifiers modifiers);int horizontalOffset() const;int verticalOffset() const;bool isIndexHidden(const QModelIndex &index) const;//将位于QRect内的数据项按照SelectionFlags(描述被选择的数据项以何种方式进行更新)//指定的方式进行更新。void setSelection(const QRect &rect,QItemSelectionModel::SelectionFlags flags);QRegion visualRegionForSelection(const QItemSelection &selection) const;
private:QItemSelectionModel *selections;  //用于保存与视图选择项相关的内容QList<QRegion> MRegionList;  //用于保存其中某一类型柱状图的区域范围,而每个区域是QList中的一个值QList<QRegion> FRegionList;QList<QRegion> SRegionList;
};#endif // HISTOGRAMVIEW_H

mainwindow.cpp

#include "mainwindow.h"
#include <QFileDialog>
#include <QFile>
#include <QTextStream>
#include <QStringList>MainWindow::MainWindow(QWidget *parent): QMainWindow(parent)
{creatAction();creatMenu();setupModel();setupView();setWindowTitle(tr("View Example"));resize(600,600);
}MainWindow::~MainWindow()
{}void MainWindow::creatAction()
{openAct=new QAction(tr("打开"),this);connect(openAct,SIGNAL(triggered(bool)),this,SLOT(slotOpen()));
}void MainWindow::creatMenu()
{fileMenu=new QMenu(tr("文件"),this);fileMenu->addAction(openAct);menuBar()->addMenu(fileMenu);
}
//新建一个model,并设置表头数据
void MainWindow::setupModel()
{model=new QStandardItemModel(4,4,this);model->setHeaderData(0,Qt::Horizontal,tr("部门"));model->setHeaderData(1,Qt::Horizontal,tr("男"));model->setHeaderData(2,Qt::Horizontal,tr("女"));model->setHeaderData(3,Qt::Horizontal,tr("退休"));
}
void MainWindow::setupView()
{/*table=new QTableView;  //新建一个QTableViewtable->setModel(model);  //为QTableView对象设置相同的ModelQItemSelectionModel *selectionModel=new QItemSelectionModel(model);table->setSelectionModel(selectionModel);//连接选择模型的selectionModel()信号与QTabelView对象的selectionChanged()槽函数//以便使自定义的HistogramView对象中的选择变化能够反映到QTabelView对象的显示中connect(selectionModel,SIGNAL(selectionChanged(QItemSelection,QItemSelection)),table,SLOT(selectionChanged(QItemSelection,QItemSelection)));splitter=new QSplitter;splitter->setOrientation(Qt::Vertical);splitter->addWidget(table);setCentralWidget(splitter);*/splitter=new QSplitter;splitter->setOrientation(Qt::Vertical);histogram=new HistogramView(splitter);  //新建一个Histogram对象histogram->setModel(model);  //为HistogramView对象设置相同的Modeltable=new QTableView;table->setModel(model);QItemSelectionModel *selectionModel=new QItemSelectionModel (model);table->setSelectionModel(selectionModel);histogram->setSelectionModel(selectionModel); //新建的QItemSelectionModel//对象作为QTableView对象和HistogramView//对象使用的选择模型splitter->addWidget(table);splitter->addWidget(histogram);setCentralWidget(splitter);//连接槽函数,以便使QTableView对象中的选择变化能够反映到自定义的HistogramView对象的显示中connect(selectionModel,SIGNAL(selectionChanged(QItemSelection,QItemSelection)),table,SLOT(selectionChanged(QItemSelection,QItemSelection)));connect(selectionModel,SIGNAL(selectionChanged(QItemSelection,QItemSelection)),histogram,SLOT(selectionChanged(QItemSelection,QItemSelection)));}
//slotOpne()槽函数完成打开标准文件对话框
void MainWindow::slotOpen()
{QString name;name=QFileDialog::getOpenFileName(this,"打开",".","histogram files(*.txt)");if(!name.isEmpty()){openFile(name);}
}
//openFile()函数完成打开所选的文件的内容
void MainWindow::openFile(QString path)
{if(!path.isEmpty()){QFile file(path);if(file.open(QFile::ReadOnly | QFile::Text)){QTextStream stream(&file);QString line;model->removeRows(0,model->rowCount(QModelIndex()),QModelIndex());int row=0;do{line=stream.readLine();if(!line.isEmpty()){model->insertRows(row,1,QModelIndex());QStringList pieces=line.split(",",QString::SkipEmptyParts);model->setData(model->index(row,0,QModelIndex()),pieces.value(0));model->setData(model->index(row,1,QModelIndex()),pieces.value(1));model->setData(model->index(row,2,QModelIndex()),pieces.value(2));model->setData(model->index(row,3,QModelIndex()),pieces.value(3));row++;}}while(!line.isEmpty());file.close();}}  //end if(!path.isEmpty())
}

histogramview.cpp

#include "histogramview.h"
#include <QPainter>HistogramView::HistogramView(QWidget *parent):QAbstractItemView(parent)
{}
//paintEvent()函数完成柱状统计图绘制的工作
void HistogramView::paintEvent(QPaintEvent *)
{//以viewport()作为绘图设备新建一个QPainter对象QPainter painter(viewport());painter.setPen(Qt::black);int x0=40;int y0=250;/*完成了x,y坐标轴的绘制,并标注坐标轴的变量*///y坐标轴painter.drawLine(x0,y0,40,30);painter.drawLine(38,32,40,30);painter.drawLine(40,30,42,32);painter.drawText(20,30,tr("人数"));for(int i=0;i<5;i++){painter.drawLine(-1,-i*50,1,-i*50);painter.drawText(-20,-i*50,tr("%1").arg(i*5));}//x轴painter.drawLine(x0,y0,540,250);painter.drawLine(538,248,540,250);painter.drawLine(540,250,538,252);painter.drawText(545,250,tr("部门"));int posD=x0+20;int row;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;}/*完成了表格第1列数据的柱状统计图的绘制*///男int posM=x0+20;MRegionList.clear();for(row=0;row<model()->rowCount(rootIndex());row++){QModelIndex index=model()->index(row,1,rootIndex());int male=model()->data(index).toDouble();int width=10;//使用不同画刷颜色区别选中与未被选中的数据项if(selections->isSelected(index)){//Qt::Dense3Pattern是QBrush style//如果被选中,则画刷的style改变painter.setBrush(QBrush(QColor(91,75,0,255),Qt::Dense3Pattern));}else{painter.setBrush(Qt::blue);}//根据当前数据项的值按照比例绘制一个方形表示此项数据painter.drawRect(QRect(posM,y0-male*10,width,male*10));QRegion regionM(posM,y0-male*10,width,male*10);//将此数据所占据的区域保存到MRegionList列表中,为后面的数据项做准备MRegionList.insert(row,regionM);posM+=50;} //end for(row=0;row<model()->rowCount(rootIndex());row++)/*完成了表格第2列数据的柱状统计图绘制*///女int posF=x0+30;FRegionList.clear();for(row=0;row<=model()->rowCount(rootIndex());row++){QModelIndex index=model()->index(row,2,rootIndex());int female=model()->data(index).toDouble();int width=10;if(selections->isSelected(index)){painter.setBrush(QBrush(Qt::red,Qt::Dense3Pattern));}else{painter.setBrush(Qt::red);}painter.drawRect(QRect(posF,y0-female*10,width,female*10));QRegion regionF(posF,y0-female*10,width,female*10);FRegionList.insert(row,regionF);posF+=50;}  //end for(row=0;row<=model()->rowCount(rootIndex());row++)/*完成了表格第3列数据的柱状统计图的绘制*///退休int posS=x0+40;SRegionList.clear();for(row=0;row<=model()->rowCount(rootIndex());row++){QModelIndex index=model()->index(row,3,rootIndex());int retire=model()->data(index).toDouble();int width=10;if(selections->isSelected(index)){painter.setBrush(QBrush(Qt::green,Qt::Dense3Pattern));}else{painter.setBrush(Qt::green);}painter.drawRect(QRect(posS,y0-retire*10,width,retire*10));QRegion regionS(posS,y0-retire*10,width,retire*10);SRegionList.insert(row,regionS);posS+=50;}  //end for(row=0;row<=model()->rowCount(rootIndex());row++)
}
//dataChanged函数实现当model中的数据更改时,调用绘图设备的update()函数
//进行更新,反映数据的变化
void HistogramView::dataChanged(const QModelIndex &topLeft,const QModelIndex &bottomRight)
{QAbstractItemView::dataChanged(topLeft,bottomRight);viewport()->update();
}
//setSelectionModel()函数为selections赋初值
void HistogramView::setSelectionModel(QItemSelectionModel *selectionModel)
{selections=selectionModel;
}
//selectionChanged()函数中完成当数据项发生变化时调用update()函数
//重绘绘图设备即可工作
void HistogramView::selectionChanged(const QItemSelection &selected,const QItemSelection &deselected)
{viewport()->update();
}
//鼠标按下事件函数mousePressEvent(),在调用setSelection()函数时确定鼠标单击
//点是否在某个数据项的区域内,并设置选择项
void HistogramView::mousePressEvent(QMouseEvent *event)
{QAbstractItemView::mousePressEvent(event);setSelection(QRect(event->pos().x(),event->pos().y(),1,1),QItemSelectionModel::SelectCurrent);
}
void HistogramView::setSelection(const QRect &rect,QItemSelectionModel::SelectionFlags flags)
{int rows=model()->rowCount(rootIndex());  //获取总行数int columns=model()->columnCount(rootIndex());  //获取总列数//用于保存被选中的数据项的Index值,此处只实现了用鼠标单击选择,而没有实现//鼠标拖曳框选,因此,鼠标动作只可能选中一个数据项。若实现框选,则可使用//QModelIndexList来保存所有被选中的数据项的Index值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);  //返回指定index的数据项所占用的区域if(!region.intersected(rect).isEmpty())selectedIndex=index;}}if(selectedIndex.isValid())selections->select(selectedIndex,flags);else{QModelIndex noIndex;selections->select(noIndex,flags);}
}
QModelIndex HistogramView::indexAt(const QPoint &point) const
{QPoint newPoint(point.x(),point.y());QRegion region;//男 列foreach(region,MRegionList)  //检查当前点是否处于第一列(男)数据的区域中{if(region.contains(newPoint)){int row=MRegionList.indexOf(region);QModelIndex index=model()->index(row,1,rootIndex());return index;}}//女 列foreach(region,FRegionList){if(region.contains(newPoint)){int row=FRegionList.indexOf(region);QModelIndex index=model()->index(row,2,rootIndex());return index;}}//合计 列foreach(region,FRegionList){if(region.contains(newPoint)){int row=FRegionList.indexOf(region);QModelIndex index=model()->index(row,2,rootIndex());return index;}}return QModelIndex();
}
QRect HistogramView::visualRect(const QModelIndex &index)const{}
void HistogramView::scrollTo(const QModelIndex &index,ScrollHint){}
QModelIndex HistogramView::moveCursor(QAbstractItemView::CursorAction cursorAction, Qt::KeyboardModifiers modifiers){}
int HistogramView::horizontalOffset()const{}
int HistogramView::verticalOffset()const{}
bool HistogramView::isIndexHidden(const QModelIndex &index)const{}
QRegion HistogramView::visualRegionForSelection(const QItemSelection & selection)const{}
QRegion HistogramView::itemRegion(QModelIndex index)
{QRegion region;if (index.column() == 1)        //男region = MRegionList[index.row()];if (index.column() == 2)        //女region = FRegionList[index.row()];if (index.column() == 3)        //退休region = SRegionList[index.row()];return region;
}

main.cpp

#include "mainwindow.h"
#include <QApplication>int main(int argc, char *argv[])
{QApplication a(argc, argv);MainWindow w;w.show();return a.exec();
}

注意.pro文件如下

#-------------------------------------------------
#
# Project created by QtCreator 2018-09-05T19:29:45
#
#-------------------------------------------------QT       += core guigreaterThan(QT_MAJOR_VERSION, 4): QT += widgetsTARGET = CH803
TEMPLATE = appDEFINES += QT_DEPRECATED_WARNINGS  #新增加的SOURCES += main.cpp\mainwindow.cpp \histogramview.cppHEADERS  += mainwindow.h \histogramview.h

在该目录下新建文件histogram.txt

E:\QT\CH803\build-CH803-Desktop_Qt_5_6_2_MinGW_32bit-Debug

内容如下

一部,12,3,5
二部,16,4,0
三部,18,4,2
四部,10,3,1
五部,11,4,3
六部,12,2,4
七部,14,3,5
八部,9,1,1

运行效果如下

备注
这个程序里有几个函数我还是没搞懂,不太清楚其中的逻辑

void HistogramView::setSelection(const QRect &rect,QItemSelectionModel::SelectionFlags flags)
QModelIndex HistogramView::indexAt(const QPoint &point) const

参考资料《Qt5开发及实例》

转载于:https://www.cnblogs.com/Manual-Linux/p/9679342.html

Qt5模型/视图结构-视图(View)相关推荐

  1. MVC模式和文档/视图结构

    MVC(Model-View-Controller)模式的基本思想是数据,显示和处理相分离.模型(Model)负责数据管理,视图(View)负责数据显示,控制器(Controller)负责业务逻辑和响 ...

  2. linux创建mysql视图_MySQL视图基本操作

    1.准备工作 在MySQL数据库中创建两张表balance(余额表)和customer(客户表)并插入数据. create table customer( id int(10) primary key ...

  3. Qt5开发学习之模型/视图结构(十)

    Qt MVC概述 MVC是一种与用户界面相关的设计模式.通过使用此模型,可以有效地分离数据和用户界面.MVC设计模式包含三要素:表示数据的模型(Model).表示用户界面的视图(View)和定义了用户 ...

  4. Qt5入门学习——模型/视图结构

    文章目录 概述 基本概念 简单文件目录浏览器[简单示例] 模型(Model) 自定义模型[示例] 视图(View) 表格数据显示[示例] 代理(Delegate) 利用Delegate设计表格控件[示 ...

  5. Qt模型model、视图view、代理

    例子为qt5应用及实例第8章 MVC是一种与用户界面相关的设计模式.通过使用此模型,可以有效地分离数据和用户界面.MVC设计模式包含三要素:表示数据的模型(Model).表示用户界面的视图(View) ...

  6. pyqt5 qstring在哪个库_PyQt模型/视图结构编程示例:QStringListModel的用法

    引言 Python是一种面向对象的高级动态编程语言,相比于其它如C/C++语言,具有上手快.代码少.开发效率高的特点,Qt是跨平台的C++图形用户界面应用程序开发框架,是当前主流的GUI开发工具之一, ...

  7. 【Qt】模型/视图结构和数据绑定控件

    模型/视图结构 模型/视图是指处理数据的模型和向用户提供GUI的视图,这是从GUI分离数据的一种结构,又称为MVC(Model-View-Controller). 模型 QAbstractItemMo ...

  8. Qt中模型/视图结构

    8.1 概述 MVC设计模式是起源于Smalltalk的一种与用户界面相关的设计模式.通过使用此模型,可以有效地分离数据和用户界面.MVC设计模式包括三个元素:表示数据的模型 (Model).表示用户 ...

  9. QT学习笔记14(Qt模型视图结构)

    一.基础知识 1.MVC设计模式:是一种与用户界面相关的设计模式,通过此模式,可以有效的分离数据和用户界面. MVC包括三个要素: 表示数据的模型(Model):应用程序的对象 表示用户界面的视图(V ...

最新文章

  1. 个人随笔——衰人自叙卷壹
  2. RedHat系统常用的日志文件详解三
  3. SpringBoot 报错Field XXX required a bean of type XXX that could not be found.
  4. GridControl详解(八)菜单
  5. 如何创建最简单的 ABAP 数据库表,以及编码从数据库表中读取数据 (上) 试读版
  6. cloud foundry_Cloud Foundry Java客户端–流事件
  7. 扩展插件_Adobe扩展工具插件系列
  8. Java ArrayList与LinkedList数据结构和特点
  9. 【今日CS 视觉论文速览】14 Dec 2018
  10. bootstrap-干货小结
  11. 【电商系统】—项目缺陷管理(二)
  12. Security+ 学习笔记53 供应链风险
  13. Flash builder 4.6 下载 破解 序列号【你懂的】
  14. 高效能人士的七个习惯简介
  15. devise第三方认证插件
  16. 华为机试(JAVA)真题Od【A卷+B卷】
  17. python 在软件自己自动输入器_Python自动操作GUI神器PyAutoGUI
  18. 高德地图上线新能源导航 一站式充电服务缓解里程焦虑
  19. Linux下载hfs文件,linux读写mac HFS+
  20. 金融行业市场占有率超五成,ZDNS筑牢金融科技网络根基

热门文章

  1. 使用 Scala 写WordContext程序
  2. 《Android安全技术揭秘与防范》—第8章8.5节Hook检测/修复
  3. Java Swing编程之仿js树状折叠菜单
  4. 理解离散傅立叶变换(一. 傅立叶变换的由来)
  5. Socket模型详解
  6. 3/100. Merge Two Binary Trees
  7. C语言经典算法100例
  8. Linux mount 修改文件系统的读写属性
  9. java 基本数据类型及自己主动类型提升
  10. 1028. 人口普查(20)