前面也写了一个关于折线的,可是那个太...,暑假没事在家又弄了一个,希望它能够有一点可适应性和扩展性。
下面是代码实现
/************************************************* 折线图绘制 author 周翔 2012-8-14 *************************************************/ #ifndef LINEGRAPHWIDGET_H #define LINEGRAPHWIDGET_H #include <QWidget> #include <QPen> #include <QPainter> #include <QResizeEvent> //#include <QDebug> #include <QTimer> struct point { int x; int y; }; class LineGraphWidget : public QWidget { Q_OBJECT public: //mix和max为折线的y轴的数据范围 explicit LineGraphWidget(int mix, int max,QWidget *parent = 0); void setSingleUnitX(const int &value) {singleUnitX = value;}//设置x轴的一个单位占多少个像素,默认10 //支持定时器定时更新 void startUpdataTimer(int msecond); void stopUpdataTimer(); signals: //支持实时更新 void newDataCome();//有新数据到来时发出的折线图更新信号 public slots: void showData(const int &data);//接受来之外部的数据 protected: void paintEvent(QPaintEvent *); void resizeEvent(QResizeEvent *e); private: QList<int> xList; QList<int> yList; int Counter; //窗口的长和宽 int widgetX; int widgetY; //折线图的显示范围 int rangeMin; int rangeMax; //根据窗口和范围得出的单位长,x轴,y轴 int singleUnitX; int singleUnitY; //根据窗口得出的多少个单位,x轴,y轴 int sumUnitX; int sumUnitY; point basePoint;//折线图的原点 point xAxisEndPoint;//X轴的终点 point yAxisEndPoint;//Y轴的终点 QTimer *timer; void getSumUnitX(); void getSingleUnitY(); void initGraph(); }; #endif // LINEGRAPHWIDGET_H #include "linegraphwidget.h" LineGraphWidget::LineGraphWidget(int mix, int max, QWidget *parent) : QWidget(parent), rangeMin(mix), rangeMax(max), singleUnitX(10), timer(NULL) { connect(this,SIGNAL(newDataCome()),this,SLOT(update())); } void LineGraphWidget::paintEvent(QPaintEvent *) { int i; int a,b,c,d; Counter = 0; QPixmap pix(widgetX,widgetY); QPainter painter(&pix); pix.fill(Qt::white); QPen pen; pen.setBrush(Qt::darkGreen); painter.setPen(pen); QPen pen1; pen1.setBrush(Qt::black); painter.setRenderHint(QPainter::Antialiasing); for(i = 0;i < sumUnitX; ++i) { a = basePoint.x + i*singleUnitX; b = basePoint.y; c= a; d = yAxisEndPoint.y; painter.drawLine(a,b,c,d); } for(i = 0; i < sumUnitY+1; ++i) { a = basePoint.x; b = basePoint.y - singleUnitY*i; c = xAxisEndPoint.x; d = b; painter.drawLine(a,b,c,d); } painter.setPen(pen1); for (i = 0;i < (sumUnitY/2+1);++i) { QRectF rectF(0,basePoint.y - singleUnitY*i*2 - 5,basePoint.x,(widgetY - basePoint.y)/3); painter.drawText(rectF,Qt::AlignCenter,QString::number(rangeMin+i*20)); } for (i = 0;i < sumUnitX/5;++i) { QRectF rectF(basePoint.x+singleUnitX*(5*i+3),basePoint.y,singleUnitX*4,widgetY-basePoint.y); painter.drawText(rectF,Qt::AlignCenter,QString::number(5*(i+1)*singleUnitX)); } int size = xList.size(); while(Counter < (size -1)) { painter.drawLine(basePoint.x + xList.value(Counter)*singleUnitX, basePoint.y - ((yList.value(Counter) - rangeMin)/10.0)*singleUnitY, basePoint.x + xList.value(Counter + 1)*singleUnitX, basePoint.y - ((yList.value(Counter + 1) - rangeMin)/10.0)*singleUnitY); Counter++; } painter.end(); painter.begin(this); painter.drawPixmap(0,0,pix); painter.end(); Counter = 0; } void LineGraphWidget::resizeEvent(QResizeEvent * e) { if (e->oldSize() != size()) { initGraph(); } } void LineGraphWidget::showData(const int &data) { //这里还要进行相关的数据正确性检测,不能超过图的范围 if (data > rangeMax || data < rangeMin) { return; } int xsize = xList.size(); int yValue = data; if (xsize == sumUnitX) { xList.clear(); yList.clear(); xsize = xList.length(); } if (xsize >= 1) { xList.insert(xsize,xsize); yList.insert(xsize,yValue); emit newDataCome(); } else { xList.insert(xsize,xsize); yList.insert(xsize,yValue); } } void LineGraphWidget::getSumUnitX() { if ((static_cast<int>(widgetX*0.85))%singleUnitX == 0){ sumUnitX = (static_cast<int>(widgetX*0.85))/singleUnitX; } else { sumUnitX = (static_cast<int>(widgetX*0.85))/singleUnitX + 1; } } void LineGraphWidget::getSingleUnitY() { int range = rangeMax - rangeMin; if (range == 0) { sumUnitY = range/10 + 1; } else { sumUnitY = range/10 + 2; } singleUnitY = (static_cast<int>(widgetY*0.85))/sumUnitY; } void LineGraphWidget::initGraph() { widgetX = size().width(); widgetY = size().height(); basePoint.x = static_cast<int>(widgetX*0.1); basePoint.y = static_cast<int>(widgetY*0.9); yAxisEndPoint.x = basePoint.x; yAxisEndPoint.y = static_cast<int>(widgetY*0.05); xAxisEndPoint.x = static_cast<int>(widgetX*0.95); xAxisEndPoint.y = basePoint.y; getSumUnitX(); getSingleUnitY(); } void LineGraphWidget::startUpdataTimer(int msecond) { if (timer != NULL) { if (timer->isActive()) { timer->stop(); } delete timer; } disconnect(SIGNAL(newDataCome())); timer = new QTimer; connect(timer,SIGNAL(timeout()),this,SLOT(update())); timer->start(msecond); } void LineGraphWidget::stopUpdataTimer() { if (timer == NULL) { } else { timer->stop(); delete timer; } }
这篇博客还是去年暑假写的,下面几位仁兄,纠结与main函数怎么写,我很是....,我认为这不是问题。
还是我把代码注释一下吧
/************************************************* 折线图绘制 author 周翔 2012-8-14 对外提供接口 void showData(int data);接受外部的折线数据 void setSingleUnitX(const int &value);设置x轴的单位像素 void startUpdataTimer(int msecond);定时器更新折线图 void stopUpdataTimer();关闭定时器 *************************************************/ #ifndef LINEGRAPHWIDGET_H #define LINEGRAPHWIDGET_H #include <QWidget> #include <QPen> #include <QPainter> #include <QResizeEvent> //#include <QDebug> #include <QTimer> struct point { int x; int y; }; class LineGraphWidget : public QWidget { Q_OBJECT public: //mix和max为折线的y轴的数据范围 explicit LineGraphWidget(int min, int max, QWidget *parent = 0); void setSingleUnitX(const int &value) {singleUnitX = value;}//设置x轴的一个单位占多少个像素,默认10 //支持定时器定时更新 void startUpdataTimer(int msecond); void stopUpdataTimer(); signals: //支持实时更新 void newDataCome();//有新数据到来时发出的折线图更新信号 public slots: /** * @brief showData * @param adress 地址 * @param _data 数据 */ void showData(const QString& adress,int _data);//接受来之外部的数据 /** * @brief slt_showData 接受外部数据 * @param name 设备名 * @param _data 数据 */ void slt_showData(ushort name,int _data); protected: void paintEvent(QPaintEvent *); void resizeEvent(QResizeEvent *e); private: QString m_currentNodeAdress;//当前显示的节点的地址 ushort m_currentNodeName;//当前节点的设备名 QList<int> xList; QList<int> yList; int Counter; //窗口的长和宽 int widgetX; int widgetY; //折线图的显示范围 int rangeMin; int rangeMax; //根据窗口和范围得出的单位长,x轴,y轴 int singleUnitX; int singleUnitY; //根据窗口得出的多少个单位,x轴,y轴 int sumUnitX; int sumUnitY; point basePoint;//折线图的原点 point xAxisEndPoint;//X轴的终点 point yAxisEndPoint;//Y轴的终点 QTimer *timer; void getSumUnitX(); void getSingleUnitY(); void initGraph(); void flush();//数据传入的节点不是现在的当前的节点的时候,刷新画面,清除所有的值 }; #endif // LINEGRAPHWIDGET_H