通过利用自定义的View,实现一个对TableModel的表格数据进行显示的柱状统计图例子,以此介绍如何应用自定义的View。
具体实现步骤如下。
(1)完成主窗体,以便显示View的内容。MainWindow 类继承自QMainWindow类,作为主窗体。以下是头文件“mainwindow.h”的具体代码。

#include <QMainWindow>
#include <QStandardItemModel>
#include <QTableView>
#include <QMenuBar>
#include <QMenu>
#include <QAction>
#include <QSplitter>
class MainWindow : public QMainWindow
{Q_OBJECT
public:MainWindow(QWidget *parent = 0);~MainWindow();void createAction();void createMenu();void setupModel();void setupView();
private:QMenu *fileMenu;QAction *openAct;QStandardItemModel *model;QTableView *table;QSplitter *splitter;
};

(2)下面是源文件“mainwindow.cpp”中的具体代码:

#include "mainwindow.h"
#include <QItemSelectionModel>
MainWindow::MainWindow(QWidget *parent): QMainWindow(parent)
{createAction();createMenu();setupModel();setupView();setWindowTitle(tr("View Example"));resize(600,600);
}
MainWindow::~MainWindow()
{}
void MainWindow::createAction()
{openAct = new QAction(tr("打开"),this);
}
void MainWindow::createMenu()
{fileMenu = new QMenu(tr("文件"),this);fileMenu->addAction(openAct);menuBar()->addMenu(fileMenu);
}

setupModel()函数新建一个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("退休"));
}

setupView()函数的具体实现代码如下:

void MainWindow::setupView()
{table = new QTableView;           //新建一个QTableView对象table->setModel(model);            //为QTableView对象设置相同的ModelQItemSelectionModel *selectionModel=new QItemSelectionModel(model);   //新建一个QItemSelectionModel对象作为QTableView对象使用的选择模型。table->setSelectionModel(selectionModel);connect(selectionModel,SIGNAL(selectionChanged(QItemSelection, ItemSelection)),table,SLOT(selectionChanged(QItemSelection,QItemSelection)));   //连接选择模型的selectionChanged()信号与QTableView对象的selectionChanged()槽函数,以便使自定义的HistogramView对象中的选择变化能够反映到QTableView对象的显示中splitter = new QSplitter;splitter->setOrientation(Qt::Vertical);splitter->addWidget(table);setCentralWidget(splitter);
}

此时运行效果如图所示:

以上只是实现了简单的主窗体框架显示,还没有完成事件。具体实现步骤如下。
(1)在头文件“mainwindow.h”中添加代码如下:

public:void openFile(QString);
public slots:void slotOpen();

(2)在源文件mainwindow.cpp中添加代码如下:

#include <QFileDialog>
#include <QFile>
#include <QTextStream>
#include <QStringList>

其中,在createAction()函数中添加代码如下:

connect(openAct,SIGNAL(triggered()),this,SLOT(slotOpen()));

slotOpen()槽函数完成打开标准文件对话框,具体代码如下:

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();}}
}

新建一个文本文件,命名为“histogram.txt”,保存在项目build-ViewEx-Desktop_Qt_5_9_0_MinGW_32bit-Debug目录下,加载文件数据后的运行效果如图所示。

具体实现步骤如下。
(1)自定义HistogramView类继承自QAbstractItemView类,用于对表格数据进行柱状图显示。下面是头文件“histogramview.h”的具体代码。

#include <QAbstractItemView>
#include <QItemSelectionModel>
#include <QRegion>
#include <QMouseEvent>
class HistogramView : public QAbstractItemView
{Q_OBJECT
public:HistogramView(QWidget *parent=0);//虚函数声明                                            //visualRect()、scrollTo()、indexAt()、moveCursor()、horizontalOffset()、verticalOffset()、isIndexHidden()、setSelection()和visualRegionForSelection():QAbstractItemView 类中的纯虚函数。这些纯虚函数不一定都要实现,可以根据需要选择性地实现,但一定要声明。QRect visualRect(const QModelIndex &index)const;void scrollTo(const QModelIndex &index,ScrollHint hint= EnsureVisible);QModelIndex indexAt(const QPoint &point)const;      //当鼠标在视图中单击或位置发生改变时被触发,它返回鼠标所在点的QModelIndex值。//为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;void setSelection(const QRect &rect,QItemSelectionModel:: SelectionFlags flags);                                                          //将位于QRect内的数据项按照SelectionFlags(描述被选择的数据项以何种方式进行更新)指定的方式进行更新。QRegion visualRegionForSelection(const QItemSelection &selection) const;private:QItemSelectionModel *selections;                 //用于保存与视图选择项相关的内容。QList<QRegion> MRegionList;                         //用于保存其中某一类型柱状图的区域范围,而每个区域是QList中的一个值。QList<QRegion> FRegionList;QList<QRegion> SRegionList;
};

(2)源文件“histogramview.cpp”的具体代码如下:

#include "histogramview.h"
#include <QPainter>
HistogramView::HistogramView(QWidget parent):QAbstractItemView(parent)
{}
//paintEvent()函数具体完成柱状统计图的绘制工作
void HistogramView::paintEvent(QPaintEvent *)
{QPainter painter(viewport());                  //以viewport()作为绘图设备新建一个QPainter对象。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=1;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))                            //使用不同画刷颜色区别选中与未被选中的数据项。painter.setBrush(QBrush(Qt::blue,Qt::Dense3Pattern));elsepainter.setBrush(Qt::blue);painter.drawRect(QRect(posM,y0-male*10,width,male*10));     //根据当前数据项的值按比例绘制一个方形表示此数据项。QRegion regionM(posM,y0-male*10,width,male*10);MRegionList.insert(row,regionM);                              //将此数据所占据的区域保存到MRegionList列表中,为后面的数据项选择做准备。posM+=50;}/* 完成了表格第2列数据的柱状统计图的绘制 */                         //完成了表格第2列数据的柱状统计图的绘制。同样,使用不同的画刷颜色区别选中与未被选中的数据项,同时保存每个数据项所占的区域至FRegionList列表中。//女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));elsepainter.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;}/* 完成了表格第3列数据的柱状统计图的绘制 */                         //完成了表格第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));elsepainter.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;}
}

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;
}

setSelection()函数的具体代码如下:

void HistogramView::setSelection(const QRect &rect,QItemSelectionModel
::SelectionFlags flags)
{int rows = model()->rowCount(rootIndex());     //获取总行数int columns = model()->columnCount(rootIndex()); //获取总列数QModelIndex selectedIndex;               //用于保存被选中的数据项的Index值。此处只实现用鼠标单击选择,而没有实现用鼠标拖曳框选,因此,鼠标动作只可能选中一个数据项。若需实现框选,则可使用QModelIndexList来保存所有被选中的数据项的Index值。for(int row=0; row<rows; ++row)            //确定在rect中是否含有数据项。此处采用遍历的方式将每个数据项的区域与rect区域进行intersected操作,获得两者之间的交集。若此交集不为空,则说明此数据项被选中,将它的Index值赋给selectedIndex。{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())               //完成select()函数的调用,即完成最后对选择项的设置工作。select()函数是在实现setSelection()函数时必须调用的。selections->select(selectedIndex,flags);else{QModelIndex noIndex;selections->select(noIndex,flags);}
}

indexAt()函数的具体内容如下:

QModelIndex HistogramView::indexAt(const QPoint &point)const
{QPoint newPoint(point.x(),point.y());QRegion region;//男 列foreach(region,MRegionList)                           //检查当前点是否处于第1列(男)数据的区域中。{if(region.contains(newPoint)){int row = MRegionList.indexOf(region);QModelIndex index = model()->index(row,1,rootIndex());return index;}}//女 列foreach(region,FRegionList)                           //检查当前点是否处于第2列(女)数据的区域中。{if(region.contains(newPoint)){int row = FRegionList.indexOf(region);QModelIndex index = model()->index(row,2,rootIndex());return index;}}//合计 列foreach(region,SRegionList)                          //检查当前点是否处于第3列(合计)数据的区域中。{if(region.contains(newPoint)){int row = SRegionList.indexOf(region);QModelIndex index = model()->index(row,3,rootIndex());return index;}}return QModelIndex();
}

由于本例未用到以下函数的功能,所以没有实现具体内容,但仍然要写出函数体的框架,代码如下:

QRect HistogramView::visualRect(const QModelIndex &index)const{}
void HistogramView::scrollTo(const QModelIndex &index,ScrollHint){}
QModelIndex HistogramView::moveCursor(QAbstractItemView::CursorAction cursor Action, 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{}

itemRegion()函数的具体代码如下:

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;
}

(4)在头文件“mainwindow.h”中添加代码如下:

#include "histogramview.h"
private:HistogramView *histogram;

(5)在源文件“mainwindow.cpp”中添加代码,其中,setupView()函数的代码修改如下:

void MainWindow::setupView()
{splitter = new QSplitter;splitter->setOrientation(Qt::Vertical);histogram = new HistogramView(splitter);//新建一个HistogramView对象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);
connect(selectionModel,SIGNAL(selectionChanged(QItemSelection,QItemSelection)),table,SLOT(selectionChanged(QItemSelection,QItemSelection)));
connect(selectionModel,SIGNAL(selectionChanged(QItemSelection,QItemSelection)),histogram,SLOT(selectionChanged(QItemSelection,QItemSelection)));                                                            //连接选择模型的selection Changed()信号与HistogramView对象的selectionChanged()槽函数,以便使QTableView对象中的选择变化能够反映到自定义的HistogramView对象的显示中。
}

运行效果如图所示:

QT学习:视图(View)练习相关推荐

  1. Qt学习: Model/View实现表格和统计图

    博主QQ:1356438802 一.简介 Model/View结构使数据管理与相应的数据显示相互独立,并提供了一系列标准的函数接口和用于Model模块与View模块之间的通信.它从MVC演化而来,MV ...

  2. C++Qt开发——Mode View(模型视图)

    Model/View(模型/视图)结构 简介 Model/View(模型/视图)结构是 Qt 中用界面组件显示与编辑数据的一种结构,视图(View)是显示和编辑数据的界面组件,模型(Model)是视图 ...

  3. Oracle 学习笔记 11 -- 视图 (VIEW)

    本次必须学习一个全新的概念-- 视图 (VIEW).在前面的笔记中曾提到过,数据对象包含:表.视图.序列.索引和同义词.前面的笔记都是对表的想剖析,那么本次笔记就对视图的世界进行深入的剖析. 视图是通 ...

  4. Qt学习笔记-----Model/View架构

    为了实现数据的存储和表现分离,Qt提供了Model/View架构,包括三个部分,分别是模型(Model),视图(View),委托(delegate). Model用于访问底层数据,也就是说为其他组件访 ...

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

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

  6. mysql视图view 自增id_MySQL学习笔记之MySQL视图(view)

    一.基本概念 视图(view)是一种虚拟存在的表,作为一个select语句保存在数据字典中,其本身并不包含任何数据.视图的数据来自定义视图的查询中使用的表,使用视图动态获取数据. 基表:创建视图时使用 ...

  7. Qt学习笔记之数据库

    一.数据库简介 1.1.数据和数据库(DB) 用计算机进行数据处理,首先就要把信息以数据形式存储到计算机中,故数据是可以被计算机接受和处理的符号.根据所表示的信息特征不同,数据有不同的类别,如数字.文 ...

  8. QT学习之路2 学习笔记

    QT学习之路2 学习笔记 1.Qt 是一个著名的 C++ 应用程序框架.你并不能说它只是一个 GUI 库,因为 Qt 十分庞大,并不仅仅是 GUI 组件.使用 Qt,在一定程度上你获得的是一个&quo ...

  9. 《Qt 学习之路 2》

    Home / Qt 学习之路 2 / <Qt 学习之路 2>目录 <Qt 学习之路 2>目录 序 Qt 前言 Hello, world! 信号槽 自定义信号槽 Qt 模块简介 ...

  10. Qt图形视图框架详解-安晓辉-专题视频课程

    Qt图形视图框架详解-12227人已学习 课程介绍         介绍Qt中的Graphics View Framework,涉及View.Scene.Item的关系,如何自定义QGraphicsI ...

最新文章

  1. 08-cmake语法-set()
  2. 联想电脑的一键换机软件——乐换机
  3. Memcached与Redis
  4. linux网络编程之inet_pton和inet_ntop函数
  5. 如何快速掌握python包_如何快速掌握一个python模块?
  6. java内存区_基于jvm java内存区域的介绍
  7. 基于html5 Canvas图表库 : ECharts
  8. 杭电计算机2011年硕士研究生笔试详解
  9. esxi6.7密码设置规则_太神奇了!excel表格竟然可以设置查看密码
  10. 世界杯:裁判看了视频后判罚更重?
  11. 电脑一直显示服务器不兼容,原神PC版提示版本不兼容怎么办 PC版常见问题介绍...
  12. printf()输出格式
  13. http referer 解释及用法
  14. 二项式定理与杨辉三角
  15. java实现验证邮箱有效性
  16. HTML5+CSS大作业——汽车自驾游(10页) 主题HTM5网页设计作业成品
  17. Spring事务切面原理
  18. 如何快速将pdf表格转换成excel
  19. 校园招聘——双选会感悟(前段学习总结)
  20. ico格式的计算机图标,ico图标是什么格式的文件

热门文章

  1. Tomcat 初始化端点错误--Error initializing endpoint
  2. 博士申请 | 香港科技大学谢知遥教授实验组招收机器学习全奖博士生
  3. 今日arXiv精选 | 23篇顶会论文:ICASSP / ICCV / CIKM / ICME / AAAI
  4. 今日arXiv精选 | 29篇顶会论文:ACM MM/ ICCV/ CIKM/ AAAI/ IJCAI
  5. 语音识别:繁华背后,危机初现
  6. 报名 | “智见AI”SpringCamp:物体检测与深度神经网络模型设计
  7. F-Principle:初探深度学习在计算数学的应用
  8. 【static关键字的作用是什么?它用在什么场景?static关键字深度解析来袭】
  9. java poi excel无法添加水印替代方法
  10. sqlserver执行更新语句失败报错42S22