一个从excel读取数据到绘制成图标的控件,
#include "painterkwidget.h"
#include <QDebug>
PainterKWidget::PainterKWidget(QWidget *parent) : QWidget(parent)
{
background = QColor(255,255,255);
lineState = true;
dataSize = 0;
maxnum = 0;
mixnum = 0;
m_width = 0;
m_height = 0;
paint_width = 0;
paint_height = 0;
textHeight = 0;
leftWidth = 0;
rightWidth = 0;
coordinate = false;
space_w = 0;
space_h = 0;
count_x = 10; //坐标 分成10成
count_y = 10; //坐标 分成10成
range_x_start = 0;
range_y_start = 0;
range_x_end = 100;
range_y_end = 100;
}
void PainterKWidget::paintEvent(QPaintEvent *e)
{
//绘制准备工作,启用反锯齿
QPainter painter(this);
painter.setRenderHints(QPainter::Antialiasing);
paintInit(&painter);
//绘制背景
drawBg(&painter);
//绘制标尺
drawAxis(&painter);
//绘制数据
drawData(&painter);
}
void PainterKWidget::drawBg(QPainter *painter)
{
painter->fillRect(this->rect(), background);
}
void PainterKWidget::drawData(QPainter *painter)
{
painter->setBrush(QColor(255,25,44));//设置填充
painter->translate(leftWidth+5,2.5 * textHeight);//移动
float mincurrent = 0;//计算当前最小值
float linecurrent = 0;//计算当前最小值
for(int i = 0; i < dataSize;i++){
if(points.at(i).y1 < points.at(i).y2){//这里的大于小于代表着方向
mincurrent = points.at(i).y2;
}else{
mincurrent = points.at(i).y1;
}//这里我们取的最大值
mincurrent -= range_y_start;
float currentHeight = points.at(i).h;//绘图高度
//这里就需要减去全数据最小值mixnum
painter->drawRect((float)i*space_w*2,paint_height - (mincurrent)*space_h,space_w,currentHeight*space_h);
//下面是划线
if(lineState == true){
linecurrent = (points.at(i).y2 + points.at(i).y1) / (float)2;
linecurrent -= range_y_start;
painter->drawLine((float)i*space_w*2,paint_height - (linecurrent)*space_h,((float)i+1)*space_w*2,paint_height - (linecurrent)*space_h);
}
}
}
void PainterKWidget::drawAxis(QPainter *painter)
{
QFontMetrics metrics = painter->fontMetrics();
// 绘制外框
painter->setBrush(QBrush("white"));
painter->drawRect(0, 0, this->size().width() -1, this->size().height() - 1);
// 移动坐标系
painter->translate(leftWidth, m_height - 1.5 * textHeight);
float totalCount_Y = range_y_end - range_y_start; // 默认值差
float totalCount_X = range_x_end - range_x_start; // 默认值差
float deltaX = paint_width / count_x; // x坐标上每分的宽度
float deltaY = (float)paint_height / count_y; // y坐标上每分的宽度
// 画横坐标
if(coordinate == false){
painter->drawLine(0, 0, paint_width, 0);
for (int i = 1; i <= totalCount_X; ++i) {
QString month = QString("%1").arg(QString::number(i * totalCount_X / count_x,'f',0));
float stringWidth = metrics.width(month);
// 绘制坐标刻度
painter->drawLine(deltaX * i, 0, deltaX * i, 4);
// 绘制坐标处的月
float monthX = deltaX * (i - 1) + ((deltaX - stringWidth));
painter->drawText(monthX, textHeight, month);
}
}else{
painter->drawLine(0, -paint_height, paint_width, -paint_height);
for (int i = 1; i <= totalCount_X; ++i) {
QString month = QString("%1").arg(QString::number(i * totalCount_X / count_x,'f',0));
float stringWidth = metrics.width(month);
// 绘制坐标刻度
painter->drawLine(deltaX * i, -paint_height, deltaX * i, -paint_height + 4);
// 绘制坐标处的月
float monthX = deltaX * (i - 1) + ((deltaX - stringWidth)) ;
painter->drawText(deltaX * i - 20, -paint_height - 4,month);
}
}
// 画纵坐标
painter->drawLine(0, 0, 0, -paint_height);
//画上面H
painter->drawText(-metrics.width(tr("(y)")),
-(deltaY * count_y + textHeight / 2 + metrics.descent()),
tr("H"));
//画刻度
for (int i = 1; i <= count_y; ++i) {
QString value = QString("%1").arg(QString::number(i * totalCount_Y / count_y + range_y_start,'f',0));
int stringWidth = metrics.width(value);
// 绘制坐标刻度
painter->drawLine(-4, -i * deltaY, 0, -i * deltaY);
// 绘制坐标值
painter->drawText(-stringWidth - 4, -(deltaY * i + textHeight / 2 - metrics.ascent()), value);
}
painter->resetTransform();
}
void PainterKWidget::resizeEvent(QResizeEvent *event)
{
m_width = this->width();
m_height = this->height();
}
void PainterKWidget::wheelEvent(QWheelEvent *event)
{
}
void PainterKWidget::mousePressEvent(QMouseEvent *event)
{
}
void PainterKWidget::mouseReleaseEvent(QMouseEvent *event)
{
}
void PainterKWidget::mouseMoveEvent(QMouseEvent *event)
{
}
void PainterKWidget::setCount_x(float value)
{
count_x = value;
update();
}
void PainterKWidget::setCount_y(float value)
{
count_y = value;
update();
}
void PainterKWidget::setRange_x(float value_start,float value_end)
{
range_x_start = value_start;
range_x_end = value_end;
update();
}
void PainterKWidget::setRange_y(float value_start,float value_end)
{
range_y_start = value_start;
range_y_end = value_end;
update();
}
void PainterKWidget::setCoordinate(bool value)
{
coordinate = value;
update();
}
void PainterKWidget::setLineState(bool value)
{
lineState = value;
update();
}
#ifndef PAINTERKWIDGET_H
#define PAINTERKWIDGET_H
#include <QWidget>
#include <QPainter>
#include <QColor>
#include <QWheelEvent>
#include <QMouseEvent>
#include <QPaintEvent>
#include <QResizeEvent>
#include <QFontMetrics>
class PointParam{
public:
float y1;
float y2;
float center;
float h;
float w;
};
class PainterKWidget : public QWidget
{
Q_OBJECT
public:
explicit PainterKWidget(QWidget *parent = 0);
signals:
protected:
virtual void paintEvent(QPaintEvent *); //绘图事件
void drawBg(QPainter *painter); //画背景
void drawScaleLine(QPainter *painter); //画刻度
void drawData(QPainter *painter); //画数据
void drawAxis(QPainter *painter); //画z坐标
void paintInit(QPainter *painter); //数据初始
virtual void resizeEvent(QResizeEvent *event); //重写虚函数获取事件
virtual void wheelEvent(QWheelEvent *event); //重写虚函数获取事件
virtual void mousePressEvent(QMouseEvent *event)Q_DECL_OVERRIDE; //重写虚函数获取事件
virtual void mouseReleaseEvent(QMouseEvent *event)Q_DECL_OVERRIDE; //重写虚函数获取事件
virtual void mouseMoveEvent(QMouseEvent *event) Q_DECL_OVERRIDE; //重写虚函数获取事件
public slots:
void setData(QVector<QPoint>);
void setCount_x(float);
void setCount_y(float);
void setRange_x(float,float);
void setRange_y(float,float);
void setCoordinate(bool );
void setLineState(bool );
private:
QVector<PointParam> points; //数据
QVector<QPoint> linePoints; //划线点
QColor background; //背景颜色
float dataSize; //数据大小
float maxnum; //最大值
float mixnum; //最小值
float disparity; //值差
float m_width; //控件宽度
float m_height; //控件高度
float paint_width; //绘图宽度
float paint_height; //绘图高度
float textHeight; //文本高度
float leftWidth; //左边宽度
float rightWidth; //右边宽度
float space_w; //间隔宽度
float space_h; //间隔高度
float count_x; //坐标 分成10层
float count_y; //坐标 分成10层
float range_x_start; //坐标 范围
float range_y_start; //坐标 范围
float range_x_end; //坐标 范围
float range_y_end; //坐标 范围
bool coordinate; //x坐标在上还是下
bool lineState; //划线状态
};
#endif // PAINTERKWIDGET_H