使用 QwtPlotDirectPainter 可以一次性只绘制一个点,对于有大量快速绘图需要的地方来说,不需要使用replot,重新渲染那么多点,可以有效降低cpu使用
头文件
#include <qmath.h> #include <QVector> #include <QPointF> #include <qwt_plot_canvas.h> #include <qwt_plot_layout.h> #include <qwt_plot.h> #include <qwt_plot_curve.h> #include <qwt_plot_marker.h> #include <qwt_plot_grid.h> #include <qwt_plot_magnifier.h> #include <qwt_plot_panner.h> #include <qwt_legend.h> #include <qwt_plot_directpainter.h> #include <qwt_series_data.h> #include <qwt_symbol.h>
#include <qwt_interval.h>
一个存放数据的类
class CurveData: public QwtArraySeriesData<QPointF> { public: CurveData() { } virtual QRectF boundingRect() const { if ( d_boundingRect.width() < 0.0 ) d_boundingRect = qwtBoundingRect( *this ); return d_boundingRect; } inline void append( const QPointF &point ) { d_samples.append(point); if(point.y()<=miny) miny = point.y(); if(point.y()>=maxy) maxy = point.y(); } void clear() { d_samples.clear(); d_samples.squeeze(); d_boundingRect = QRectF( 0.0, 0.0, -1.0, -1.0 ); } // size_t size(){ // return d_samples.size(); // } public: double miny = 0; double maxy = 1; };
全局变量
QwtPlotCurve *d_curve; // 画笔 QwtPlotDirectPainter *d_directPainter; //不用replot的绘图 CurveData *curveData = nullptr; // 用于保存数据
QwtInterval d_interval; // y轴最大值,最小值
初始化
d_directPainter = new QwtPlotDirectPainter();//不重画的添加点 QwtPlotCanvas *canvas1 = new QwtPlotCanvas(); canvas1->setPaintAttribute( QwtPlotCanvas::BackingStore, false );//一种优化方式 canvas1->setBorderRadius( 5 );//画布圆角 if ( canvas1->testPaintAttribute( QwtPlotCanvas::BackingStore ) ) { canvas1->setAttribute( Qt::WA_PaintOnScreen, true ); canvas1->setAttribute( Qt::WA_NoSystemBackground, true ); } QPalette pal = canvas1->palette(); pal.setColor( QPalette::WindowText, Qt::green ); canvas1->setPalette(pal); ui->qwtPlot->setAutoReplot(false); ui->qwtPlot->setCanvas(canvas1); ui->qwtPlot->plotLayout()->setAlignCanvasToScales(true); //加入网格 QwtPlotGrid* grid = new QwtPlotGrid(); //grid->setPen(QColor(64,64,128,100),0.5); grid->setPen( Qt::gray, 0.0, Qt::DotLine ); grid->enableX( true ); grid->enableY( true ); grid->attach(ui->qwtPlot); //设置 坐标轴范围,坐标轴标题 ui->qwtPlot->setAxisScale(QwtPlot::xBottom,0,120,20); d_interval.setMaxValue(3500); d_interval.setMinValue(0); ui->qwtPlot->setAxisScale(QwtPlot::yLeft,d_interval.minValue(),d_interval.maxValue()); ui->qwtPlot->setAxisTitle(QwtPlot::yLeft,QObject::trUtf8("Temporature->")); ui->qwtPlot->setAxisTitle(QwtPlot::xBottom,QObject::trUtf8("Time[s]->")); ui->qwtPlot->setTitle(QObject::trUtf8("Teasink")); //绘制标记线,y轴在0绘制直线 x轴在中间绘制直线 //QwtPlotMarker *d_origin = new QwtPlotMarker(); //d_origin->setLineStyle( QwtPlotMarker::Cross ); //d_origin->setValue( d_interval.minValue() + d_interval.width() / 2.0, 0.0 ); //d_origin->setLinePen( Qt::gray, 0.0, Qt::DashLine ); //d_origin->attach(ui->qwtPlot); //画笔,用来绘制点 d_curve = new QwtPlotCurve(); d_curve->setStyle( QwtPlotCurve::Lines );//线条 d_curve->setPen( QColor(0,255,0),1.5,Qt::SolidLine );//设置画笔颜色 d_curve->setRenderHint( QwtPlotItem::RenderAntialiased, true );//Toggle an render hint//渲染 d_curve->setPaintAttribute( QwtPlotCurve::ClipPolygons, false );//关闭,这个优化(点超过可见区域,需要绘制出来) curveData = new CurveData(); d_curve->setData( curveData );//数据列表 QwtSeriesData<QPointF> d_curve->attach( ui->qwtPlot );
清空数据的操作 注意 不能使用 ui->qwtPlot->detachItems();因为这个操作会删除 d_curve
curveData->clear(); //ui->qwtPlot->detachItems(); ui->qwtPlot->replot(); ui->qwtPlot->show();
绘图 注意replot 不能太频繁,因此初始化范围时候最好就设置好范围
int datatemporature = msg.mid(8,2).toInt(nullptr,16); datatemporature += msg.mid(10,2).toInt(nullptr,16)*256; QPointF point; point.setX((curveData->size()+1)*0.1); point.setY(datatemporature*1.0); curveData->append(point); //一次只绘制一个点 d_directPainter->drawSeries( d_curve, curveData->size()-2, curveData->size()-1 ); int flagreplot = 0; if(curveData->miny<d_interval.minValue()){ d_interval.setMinValue(curveData->miny-curveData->miny*0.15); flagreplot = 1; } if(curveData->maxy>d_interval.maxValue()){ d_interval.setMaxValue(curveData->maxy+curveData->maxy*0.15); flagreplot = 1; } if(flagreplot>0){ ui->qwtPlot->setAxisScale(QwtPlot::yLeft,d_interval.minValue(),d_interval.maxValue()); ui->qwtPlot->replot(); }
总结,关键点是初始化,绘图这一点也有区别,不要被官方的demo吓着了.
//