/**
* 书本:【Qt5开发及实例】
* 功能:数据柱形图显示,这个类是表格显示
* 文件:mainwindow.h
* 时间:2015年1月28日18:50:54
* 作者:cutter_point
*/
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QStandardItemModel>
#include <QSplitter>
#include <QMenu>
#include <QMenuBar>
#include <QTableView>
#include <QString>
#include "histogramview.h"
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = 0);
~MainWindow();
//创建文件里面的打开动作
void createAction();
//创建菜单栏
void createMenu();
//设置模型
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
/**
* 书本:【Qt5开发及实例】
* 功能:数据柱形图显示
* 文件:mainwindow.h
* 时间:2015年1月28日18:50:54
* 作者:cutter_point
*/
#include "mainwindow.h"
#include <QFileDialog>
#include <QDebug>
MainWindow::MainWindow(QWidget *parent) //构造函数
: QMainWindow(parent)
{
createAction(); //生成相应的事件
createMenu(); //生成菜单
setupModel(); //设置模型
setupView(); //显示视图
//设置标题和界面大小
this->setWindowTitle(tr("cutter_point"));
this->resize(600, 600);
}
MainWindow::~MainWindow()
{
}
//创建文件里面的打开动作
//void createAction();
void MainWindow::createAction()
{
//创建我们的打开事件
openAct = new QAction(tr("open"), this);
//连接上打开文件
connect(openAct, SIGNAL(triggered()), this, SLOT(slotOpen())); //点击选择这个事件连接上这个槽函数
}
//创建菜单栏
//void createMenu();
void MainWindow::createMenu()
{
//设置文件菜单
fileMenu = new QMenu(tr("file"), this);
fileMenu->addAction(openAct); //为这个菜单栏加入一个选项
this->menuBar()->addMenu(fileMenu); //加入到主窗口的菜单行中
}
//设置模型
//void setupModel();
void MainWindow::setupModel()
{
model = new QStandardItemModel(4, 4, this); //在当前的窗口中创建一个4行4列的标准模型
//头标题就是4个,部门,男,女,退休
model->setHeaderData(0, Qt::Horizontal, tr("department")); //部门
model->setHeaderData(1, Qt::Horizontal, tr("male")); //男
model->setHeaderData(2, Qt::Horizontal, tr("female")); //女
model->setHeaderData(3, Qt::Horizontal, tr("retirement")); //退休
}
//设置显示视图
//void setupView();
void MainWindow::setupView()
{
//设置好表格视图
table = new QTableView;
table->setModel(model); //设置这个表格视图的模型
QItemSelectionModel *selectionModel = new QItemSelectionModel(model);
table->setSelectionModel(selectionModel);
splitter = new QSplitter; //分割界面
splitter->setOrientation(Qt::Vertical); //垂直分割
// histogram = new HistogramView;
histogram = new HistogramView(splitter);
histogram->setModel(model); //添加到这个模型中
histogram->setSelectionModel(selectionModel);
splitter->addWidget(table);
splitter->addWidget(histogram);
this->setCentralWidget(splitter);
connect(selectionModel, SIGNAL(selectionChanged(QItemSelection,QItemSelection)), table, SLOT(selectionChanged(QItemSelection,QItemSelection)));
connect(selectionModel, SIGNAL(selectionChanged(QItemSelection,QItemSelection)), histogram, SLOT(selectionChanged(QItemSelection,QItemSelection)));
}
//打开文件读取文件的槽函数
//void slotOpen();
void MainWindow::slotOpen()
{
QString name; //文件名
name = QFileDialog::getOpenFileName(this, "open", ".", "file(*.txt; *.doc)"); //设置文件打开对话框
if(!name.isEmpty()) //取得文件
{
//打开文件,读取文件里面的数据
this->openFile(name);
}
}
//读取打开的文件
// void openFile();
void MainWindow::openFile(QString path)
{
//如果得到的路径不为空
if(!path.isEmpty())
{
QFile file(path); //取得文件
qDebug()<<path; //看看路径的格式
if(file.open(QFile::ReadOnly | QFile::Text)) //打开文件里面只有文本,并且是只读格式,表示打开成功
{
QTextStream stream(&file); //文件读取流
QString line; //保存一行数据
model->removeRows(0, model->rowCount(QModelIndex()), QModelIndex()); //删除从第一个index到第二个index的行,总之先清除各行
int row = 0; //第0行
do
{
line = stream.readLine(); //读取一行
//如果读取到了数据
if(!line.isEmpty())
{
model->insertRow(row, QModelIndex()); //把第row行数据插入,那个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++;
}//if(!line.isEmpty())
}while(!line.isEmpty()); //当读取到空的数据的时候就退出
file.close(); //关闭文件流
}//if(file.open(QFile::ReadOnly | QFile::Text))
}// if(!path.isEmpty())
}//void MainWindow::openFile(QString path)
/**
* 书本:【Qt5开发及实例】
* 功能:数据柱形图显示,这个类是柱形图
* 文件:histogramview.h
* 时间:2015年1月28日20:23:40
* 作者:cutter_point
*/
#ifndef HISTOGRAMVIEW_H
#define HISTOGRAMVIEW_H
#include <QAbstractItemView>
#include <QItemSelectionModel>
#include <QRegion>
#include <QMouseEvent>
class HistogramView : public QAbstractItemView
{
Q_OBJECT
public:
explicit HistogramView(QWidget *parent = 0);
//这里有些继承来的纯虚函数,可以实现,但必须声明
// virtual QRect visualRect(const QModelIndex &index) const = 0;
// virtual void scrollTo(const QModelIndex &index, ScrollHint hint = EnsureVisible) = 0;
// virtual QModelIndex indexAt(const QPoint &point) const = 0;
QRect visualRect(const QModelIndex &index) const;
void scrollTo(const QModelIndex &index, ScrollHint hint = EnsureVisible);
QModelIndex indexAt(const QPoint &point) const;
//绘制柱形图的函数
void paintEvent(QPaintEvent *);
//为selections赋初值
// QAbstractItemView interface
void setSelectionModel(QItemSelectionModel *selectionModel);
//当鼠标在按下的时候调用setSelection函数,确定鼠标点击点所在的区域,设置选择项
void mousePressEvent(QMouseEvent *event);
//选中区域是属于什么
QRegion itemRegion(QModelIndex index);
signals:
public slots:
protected slots:
void dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight);
void selectionChanged(const QItemSelection &selected, const QItemSelection &deselected);
protected:
QModelIndex moveCursor(CursorAction cursorAction,
Qt::KeyboardModifiers modifiers);
int horizontalOffset() const;
int verticalOffset() const;
bool isIndexHidden(const QModelIndex &index) const;
void setSelection(const QRect &rect, QItemSelectionModel::SelectionFlags command);
QRegion visualRegionForSelection(const QItemSelection &selection) const;
// virtual QModelIndex moveCursor(CursorAction cursorAction,
// Qt::KeyboardModifiers modifiers) = 0;
// virtual int horizontalOffset() const = 0;
// virtual int verticalOffset() const = 0;
// virtual bool isIndexHidden(const QModelIndex &index) const = 0;
// virtual void setSelection(const QRect &rect, QItemSelectionModel::SelectionFlags command) = 0;
// virtual QRegion visualRegionForSelection(const QItemSelection &selection) const = 0;
private:
QItemSelectionModel *selections;
QList<QRegion> MRegionList;
QList<QRegion> FRegionList;
QList<QRegion> SRegionList;
};
#endif // HISTOGRAMVIEW_H
/**
* 书本:【Qt5开发及实例】
* 功能:数据柱形图显示,这个类是柱形图
* 文件:histogramview.cpp
* 时间:2015年1月28日20:36:24
* 作者:cutter_point
*/
#include "histogramview.h"
#include <QPainter> //绘画工具
#include <QDebug>
HistogramView::HistogramView(QWidget *parent) :
QAbstractItemView(parent)
{
}
//绘制柱形图的函数
//void paintEvent(QPaintEvent *);
void HistogramView::paintEvent(QPaintEvent *)
{
QPainter painter(viewport()); //这个就是在这个viewport范围内建立一个绘画对象,这个viewport就是给定的范围,大小暂时不知,反正就是一个地方
painter.setPen(Qt::yellow); //来一只黄色的笔
int x0 = 40;
int y0 = 250; //来了,坐标0号
//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++) //y坐标的刻度
{
painter.setPen(Qt::black); //来一只黑色的笔
painter.drawLine(x0, i*50, 50, i*50);
// qDebug()<<"=======Chinese????"<<i;
painter.drawText(20, (5-i)*50, tr("%1").arg(i*5));
}
//x 坐标轴
painter.setPen(Qt::yellow); //来一只黄色的笔
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(this->rootIndex()); ++row) //model() 返回已经呈现的视图
{//rootIndex统计最开始的那个索引
// qDebug()<<this->rootIndex(); //这个根索引
QModelIndex index = model()->index(row, 0, rootIndex()); //得到第row行,第1列,第0个的索引
QString dep = model()->data(index).toString(); //得到这个索引的数据
painter.drawText(posD, y0 + 20, dep); //dep就是刚得到的部门信息
posD += 50; //下一个
}
//男
// qDebug()<<"111111";
int posM=x0+20;
for(row=0; row<model()->rowCount(rootIndex()); ++row)
{
QModelIndex index=model()->index(row,1,rootIndex()); //第二列
int male=model()->data(index).toDouble(); //数值转化
// qDebug()<<index;
int width=10; //柱形图柱子的宽度
// qDebug()<<"1111111"; //注意这里selection还没有初值,也就是还没有实例对象,没有模型对象
if(selections->isSelected(index)) //用不同的颜色区别选择的部分和未选择的部分,index是这一行的索引
{
qDebug()<<"1111111ifififififif";
painter.setBrush(QBrush(Qt::black,Qt::Dense3Pattern)); //设置画刷
}
else
{
// qDebug()<<"1111111elseelseelseelse";
painter.setBrush(Qt::blue);
}
// qDebug()<<"22222";
painter.drawRect(QRect(posM,y0-male*10,width,male*10)); //画柱子,宽度已设置为10
QRegion regionM(posM,y0-male*10,width,male*10); //剪裁一个区域的大小记录下来
MRegionList<<regionM; //把占据的区域保存下来给后面使用
posM+=50;
}
// qDebug()<<"22222";
//女
// qDebug()<<"女1";
int posF=x0+30; //这里是吧位置设置到离上面为10 的地方
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)) //用不同的颜色区别选择的部分和未选择的部分,index是这一行的索引
painter.setBrush(QBrush(Qt::black,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<<regionF; //把占据的区域保存下来给后面使用
posF+=50;
}
// qDebug()<<"女2";
//退休
// qDebug()<<"退休1";
int posS=x0+40;
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)) //用不同的颜色区别选择的部分和未选择的部分,index是这一行的索引
painter.setBrush(QBrush(Qt::black,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); //就是把在(posS, y0-retire)开始高度retire*10和宽度10的区域
SRegionList<<regionS;
posS+=50;
}//for(row=0;row<model()->rowCount(rootIndex());row++)
// qDebug()<<"退休2";
}//void HistogramView::paintEvent(QPaintEvent *)
//当模型的数据改变的时候,调用绘图设备的update函数更新
void HistogramView::dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight)
{
QAbstractItemView::dataChanged(topLeft, bottomRight);
this->viewport()->update(); //在这个基础上改变更新
}
//设置selections的初值
void HistogramView::setSelectionModel(QItemSelectionModel *selectionModel)
{
selections = selectionModel;
}
QRect HistogramView::visualRect(const QModelIndex &index)const
{
QRect *p = new QRect();
return *p;
}
void HistogramView::scrollTo(const QModelIndex &index,ScrollHint){}
QModelIndex HistogramView::moveCursor(QAbstractItemView::CursorAction cursorAction, Qt::KeyboardModifiers modifiers)
{
return QModelIndex();
}
int HistogramView::horizontalOffset()const
{
return 0;
}
int HistogramView::verticalOffset()const
{
return 0;
}
bool HistogramView::isIndexHidden(const QModelIndex &index)const
{
return true;
}
QRegion HistogramView::visualRegionForSelection(const QItemSelection &selection)const
{
return QRegion();
}
//选项的更新
void HistogramView::selectionChanged(const QItemSelection &selected, const QItemSelection &deselected)
{
viewport()->update(); //更新数据
}
//当鼠标在按下的时候调用setSelection函数,确定鼠标点击点所在的区域,设置选择项
void HistogramView::mousePressEvent(QMouseEvent *event)
{
QAbstractItemView::mousePressEvent(event); //视图层的鼠标点击事件获取
qDebug()<<"mouse";
setSelection(QRect(event->pos().x(), event->pos().y(), 1, 1), QItemSelectionModel::SelectCurrent); //获取当前选择的那个区域
}
//返回选择到的数值的区域
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;
}
//设置选择的区域
void HistogramView::setSelection(const QRect &rect, QItemSelectionModel::SelectionFlags command)
{
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, command);
else
{
qDebug()<<"noindex";
QModelIndex noIndex; //空的索引
selections->select(noIndex, command);
}
}
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,SRegionList) // 合计 列
{
if (region.contains(newPoint))
{
int row = SRegionList.indexOf(region);
QModelIndex index = model()->index(row,3,rootIndex());
return index;
}
}
return QModelIndex();
}
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
没错,我就是信管专业的,就是信息管理与信息系统
原文:http://blog.csdn.net/cutter_point/article/details/43310013