Qt实现曲线的方式有多种方式,第三方库也有不少,例如QtChart,QCustomPlot,Qwt,chartDirector或者利用js也可以实现。对于不用库的优缺点就不在这里说明了。本例子只是利用Qt的QPainter实现。可以支持4.x,5.x(3.x应该也可以没有测试)。
使用如下
m_line = new CRealTimeLine;
m_line->setDrawStartLeft(false);
m_line->addDataList(datalist);
QLinearGradient liner;
liner.setColorAt(0,QColor(“#9DCEFF”));
liner.setColorAt(1,QColor(“#FFFFFF”));
m_line->setInterval(5);
m_line->setBackColor(liner);
setCentralWidget(m_line);
QTimer *timer = new QTimer(this);
connect(timer, SIGNAL(timeout()), this, SLOT(update()));
timer->start(5000);
头文件
ifndef CREALTIMELINE_H
define CREALTIMELINE_H
#include
include
#include
#include
#include "qmath.h"
class CRealTimeLine : public QWidget
{
Q_OBJECT
public:
CRealTimeLine(QObject *parent = NULL);
~CRealTimeLine();
void setXLabels(QStringList labellist);
void setYLabels(QStringList labellist);
void setDrawStartLeft(bool startleft = true); //默认从左侧
void addDataList(QList<float> dlist);
void addDataList(float value);
void removeDatas(); //清除数据
void setBackColor(QLinearGradient linegradent);
void setLineColor(QColor color);
void setMaxValue(int max);
void setPrefixText(QString text);
void setInterval(int interval);
private:
void initdata();
private:
QPainterPath drawGridding(); //网格
QPainterPath drawRectPath(); //边框
QPainterPath drawXYScalePath(); //x,y刻度
void drawXLabel(QPainter &painter);
void drawYLabel(QPainter &painter);
QPainterPath drawLineLeftPath(); //左侧开始画线
QPainterPath drawLineRigthPath(); //右侧开始画线
QPainterPath drawBack(QPainter &painter);
void drawText(QPainter &painter); //默认最后一个值
void drawLine(QPainter &painter);
private:
void paintEvent( QPaintEvent * event );
private:
QPointF m_originpoint; //原点所在位置
int m_griddingcount_x,m_griddingcount_y; //网格个数
QStringList m_xlabellist,m_ylabellist;
int m_count; //点的个数
QList<float> m_datelist; //数据
bool m_isstartleft; //画的方式,从左侧还是右侧 默认左侧
int m_ymax,m_ymin;
QList m_defaultcolors;
QLinearGradient m_backlinegradent; //背景
QColor m_linecolor;
QString m_textstr;
QDateTime m_olddateime;
int m_interval;
};
endif // CREALTIMELINE_H
`cpp文件
include “crealtimeline.h”
include
CRealTimeLine::CRealTimeLine(QObject *parent)
//: QWidget(parent)
{
m_isstartleft = false;
m_count = 30*60; //默认30分钟的数据。一秒一个
m_ymax = 100;
m_ymin = 0;
m_defaultcolors.append(QColor(“red”));
m_defaultcolors.append(QColor(“blue”));
m_defaultcolors.append(QColor(“yellow”));
m_defaultcolors.append(QColor(“green”));
m_linecolor = QColor(“green”);
m_olddateime = QDateTime::currentDateTime();
m_interval = 1;
}
CRealTimeLine::~CRealTimeLine()
{
}
void CRealTimeLine::setXLabels( QStringList labellist )
{
m_xlabellist.clear();
m_xlabellist = labellist;
}
void CRealTimeLine::setYLabels( QStringList labellist )
{
m_ylabellist.clear();
m_ylabellist = labellist;
}
void CRealTimeLine::setDrawStartLeft( bool startleft /= true/ )
{
m_isstartleft = startleft;
}
void CRealTimeLine::addDataList( QList dlist )
{
for (int i = 0 ; i < dlist.count(); ++i)
{
addDataList(dlist.at(i));
}
}
void CRealTimeLine::addDataList( float value )
{
int tmp = (int)value+1;
if (tmp > m_ymax)
{
m_ymax = tmp*1.2;
}
m_ymin = qMin(m_ymin,tmp);
if (m_isstartleft)
{
m_datelist.append(value);
if (m_datelist.count() > m_count)
m_datelist.removeFirst();
}
else
{
m_datelist.prepend(value);
if (m_datelist.count() > m_count)
m_datelist.removeLast();
}
}
void CRealTimeLine::setMaxValue( int max )
{
m_ymax = max;
}
void CRealTimeLine::removeDatas()
{
m_datelist.clear();
}
void CRealTimeLine::setLineColor( QColor color )
{
m_linecolor = color;
}
void CRealTimeLine::setBackColor( QLinearGradient linegradent )
{
m_backlinegradent = linegradent;
m_backlinegradent.setStart(QPointF(width()/2,0));
m_backlinegradent.setFinalStop(QPointF(width()/2,height()));
}
void CRealTimeLine::setPrefixText( QString text )
{
m_textstr = text;
}
void CRealTimeLine::setInterval( int interval )
{
m_interval = interval;
}
void CRealTimeLine::initdata()
{
m_originpoint.setX(width()*0.1);
m_originpoint.setY(height()*0.9);
m_griddingcount_x = 20;
m_griddingcount_y = 10;
m_xlabellist.clear();
QDateTime curtime = QDateTime::currentDateTime();
int setp = QDateTime::currentDateTime().toTime_t()-m_olddateime.toTime_t();
if (setp > m_count )
{
m_olddateime = m_olddateime.addSecs(m_interval);
}
if (m_isstartleft)
{
QTime ctime = m_olddateime.time();
for (int i = 0; i < 5; ++i)
{
QTime tmp = ctime.addSecs(i*6*60); //30分钟
m_xlabellist.append(tmp.toString("hh:mm:ss"));
}
}
else
{
QTime ctime = QDateTime::currentDateTime().time();
for (int i = 0; i < 5; ++i)
{
QTime tmp = ctime.addSecs(-i*6*60); //30分钟
m_xlabellist.push_front(tmp.toString("hh:mm:ss"));
}
}
m_ylabellist.clear();
float step = 1.0*(m_ymax - m_ymin)/10;
for (int i = 0; i < 11; ++i)
{
m_ylabellist << QString("%1").arg(m_ymin + step*i);
}
}
void CRealTimeLine::paintEvent( QPaintEvent * event )
{
initdata();
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing, true);
painter.setRenderHint(QPainter::TextAntialiasing, true);
painter.setRenderHint(QPainter::SmoothPixmapTransform, true);
QFont font;
font.setPixelSize(11);
painter.setFont(font);
painter.save();
painter.setPen(QPen(Qt::lightGray));
painter.setBrush(m_backlinegradent);
painter.drawPath(drawBack(painter));
painter.restore();
drawText(painter);
painter.save();
//painter.setBrush(m_backlinegradent);
painter.drawPath(drawRectPath());
painter.restore();
painter.save();
QPen pen;
pen.setColor(Qt::lightGray);
pen.setStyle(Qt::DotLine);
painter.setPen(pen);
painter.drawPath(drawGridding());
painter.restore();
painter.drawPath(drawXYScalePath());
drawXLabel(painter);
drawYLabel(painter);
drawLine(painter);
}
QPainterPath CRealTimeLine::drawGridding()
{
//QPainter painter(this);
QPointF oldp(m_originpoint);
//画背景虚线
QPainterPath gridding_xypath;
oldp = m_originpoint;
int w = width()*0.8;
int h = height()*0.8;
float index = 1.0*w/m_griddingcount_x;
for (int i = 0; i < m_griddingcount_x; ++i)
{
oldp.setX(oldp.x()+index);
gridding_xypath.moveTo(oldp);
gridding_xypath.lineTo(oldp.x(),oldp.y()-h);
}
oldp = m_originpoint;
index = 1.0*h/m_griddingcount_y;
for (int i = 0; i < m_griddingcount_y; ++i)
{
oldp.setY(oldp.y() - index);
gridding_xypath.moveTo(oldp);
gridding_xypath.lineTo(oldp.x()+w,oldp.y());
}
return gridding_xypath;
}
QPainterPath CRealTimeLine::drawRectPath()
{
int w = width()*0.8;
int h = height()*0.8;
QPainterPath XYPathRect;
XYPathRect.addRect(m_originpoint.x(),m_originpoint.y()-h,w,h);
return XYPathRect;
}
QPainterPath CRealTimeLine::drawBack( QPainter &painter )
{
QPainterPath XYPathRect;
XYPathRect.addRect(0,0,width(),height());
return XYPathRect;
}
QPainterPath CRealTimeLine::drawXYScalePath()
{
int w = width()*0.8;
int h = height()*0.8;
QPainterPath XYPath;
//画刻度X
QPointF oldp(m_originpoint);
float index = 1.0*w/m_griddingcount_x;
int tickcount = 5;
for (int i = 0; i < m_griddingcount_x; ++i)
{
QPointF tmppoint(oldp);
float index_tmp = index/tickcount;
tmppoint.setX(tmppoint.x()+index*i);
for (int j = 0 ; j < tickcount ;j++)
{
QPointF p(tmppoint);
int d = 0;
if (j == 0)
d = 2;
p.setX(p.x()+index_tmp*j);
XYPath.moveTo(p);
p.setY(p.y() + 5+d);
XYPath.lineTo(p);
}
}
//画刻度Y
index = 1.0*h/m_griddingcount_y;
tickcount = 1;
for (int i = 0; i < m_griddingcount_y; ++i)
{
QPointF tmppoint(oldp);
float index_tmp = index/tickcount;
tmppoint.setY(tmppoint.y()-index*i);
for (int j = 0 ; j < tickcount ;j++)
{
QPointF p(tmppoint);
int d = 0;
if (j == 0)
d = 2;
p.setY(p.y() - index_tmp*j);
XYPath.moveTo(p);
p.setX(p.x() - 5-d);
XYPath.lineTo(p);
//p.setX(p.x() + 5);
}
}
//if (m_y2_visable)
//{
// oldp =m_originpoint;
// oldp.setX(oldp.x()+m_length_x);
// for (int i = 0; i < m_tickcount_y2; ++i)
// {
// QPointF p(oldp);
// p.setY(p.y() - m_tick_y2_index*i);
// XYPath.moveTo(p);
// p.setX(p.x() + m_tick_xy);
// XYPath.lineTo(p);
// }
//}
return XYPath;
}
void CRealTimeLine::drawXLabel(QPainter &painter)
{
painter.save();
//////画X
if (m_xlabellist.isEmpty() ) return;
int w = width()*0.8;
//int h = height()*0.8;
QPointF oldp(m_originpoint);
int _height = 15;
int index = w/(m_xlabellist.count()-1);
for (int i = 0; i < m_xlabellist.count(); ++i)
{
QString textstr = m_xlabellist.at(i);
QPointF p(oldp);
p.setY(p.y()+5);
float x = p.x()+index*i-10;
float y = p.y();
QRectF rect_(x,y,textstr.length()*10,_height);
painter.drawText(rect_, Qt::AlignTop, textstr);
}
painter.restore();
}
void CRealTimeLine::drawYLabel(QPainter &painter)
{
if (m_ylabellist.isEmpty() ) return;
//int w = width()*0.8;
int h = height()*0.8;
//////画Y
QPointF oldp(m_originpoint);
int _height = 15;
int index = h/(m_ylabellist.count()-1);
for (int i = 0; i < m_ylabellist.count(); ++i)
{
QString textstr = m_ylabellist.at(i);
QPointF p(oldp);
float x = p.x()-_height*textstr.length()-10;
float y = p.y()-index*i-10;
QRectF rect_(x,y,_height*textstr.length(),20);
painter.drawText(rect_, Qt::AlignRight, textstr);
}
painter.restore();
}
void CRealTimeLine::drawText( QPainter &painter )
{
painter.save();
QFont font;
font.setPixelSize(12);
painter.setFont(font);
int w = width()*0.1;
int h = height()*0.02;
QString str;
if (m_isstartleft)
{
if (m_datelist.count() > 0)
{
QString tstr = QString::number(m_datelist.last(),’f’,2);
str = QString(“%1%2”).arg(m_textstr).arg(tstr);
}
else
str = m_textstr;
}
else
{
if (m_datelist.count() > 0)
{
QString tstr = QString::number(m_datelist.first(),'f',2);
str = QString("%1%2").arg(m_textstr).arg(tstr);
}
else
str = m_textstr;
}
QRectF rect(w,h,w*8,h*4);
painter.drawText(rect, Qt::AlignLeft, str);
painter.restore();
}
void CRealTimeLine::drawLine(QPainter &painter)
{
painter.save();
QColor color = m_linecolor;
if (m_isstartleft) //左侧开始
{
painter.setPen(QPen(color));
painter.drawPath(drawLineLeftPath());
}
else
{
painter.setPen(QPen(color));
painter.drawPath(drawLineRigthPath());
}
painter.restore();
}
QPainterPath CRealTimeLine::drawLineLeftPath()
{
QPainterPath linepath;
int w = width()*0.8;
int h = height()*0.8;
QPointF oldp(m_originpoint);
float step = 1.0*w/m_count;
float ystep = 1.0*h/(m_ymax-m_ymin);
if (m_datelist.isEmpty()) return linepath;
if (m_datelist.count() == 1)
{
linepath.moveTo(m_originpoint.x(),m_originpoint.y() - ystep*m_datelist.at(0));
linepath.lineTo(m_originpoint.x()+5,m_originpoint.y() -ystep*m_datelist.at(0));
return linepath;
}
for (int i = 0 ; i < m_datelist.count()-1; ++i)
{
linepath.moveTo(m_originpoint.x()+step*i,m_originpoint.y() - ystep*m_datelist.at(i));
linepath.lineTo(m_originpoint.x()+step*i+step,m_originpoint.y() -ystep*m_datelist.at(i+1));
}
return linepath;
}
QPainterPath CRealTimeLine::drawLineRigthPath()
{
QPainterPath linepath;
float w = width()*0.8;
int h = height()*0.8;
float step = 1.0*w/m_count;
float ystep = 1.0*h/(m_ymax-m_ymin);
if (m_datelist.isEmpty()) return linepath;
if (m_datelist.count() == 1)
{
linepath.moveTo(m_originpoint.x()+w,m_originpoint.y() - ystep*m_datelist.at(0));
linepath.lineTo(m_originpoint.x()+w-5,m_originpoint.y() -ystep*m_datelist.at(0));
return linepath;
}
//QPointF oldp(m_originpoint);
//oldp.setX(m_originpoint.x()+w-step*m_datelist.count());
for (int i = m_datelist.count()-1 ; i > 0; --i)
{
linepath.moveTo(m_originpoint.x()+w-step*i,m_originpoint.y() - ystep*m_datelist.at(i));
linepath.lineTo(m_originpoint.x()+w-step*i+step,m_originpoint.y() -ystep*m_datelist.at(i-1));
}
return linepath;
}
“`