用qwt绘制AD波形

引子

     项目终于快完成了,现在开始整理下代码,总结下,今天先分享下关于使用如何用QWT绘制波形,先把图给贴出来。


关于QWT

    以下源于百度百科“QWT全称是Qt Widgets for TechnicalApplications,是一个基于LGPL版权协议的开源项目,可生成各种统计图。它为具有技术专业背景的程序提供GUI组件和一组实用类,其目标是以基于2D方式的窗体部件来显示数据,数据源以数值,数组或一组浮点数等方式提供,输出方式可以是Curves(曲线),Slider(滚动条),Dials(圆盘),Compasses(仪表盘)等等。该工具库基于Qt开发,所以也继承了Qt的跨平台特性。”

   我使用的是qwt-6.0.0-rc5,可以到官网下载http://qwt.sourceforge.net/,具体的安装和集成过程可以参照http://www.cuteqt.com/blog/?p=994这个贴子。

源码

“AdPlot.h”

   1: #ifndef ADPLOT_H
   2: #define ADPLOT_H
   3:  
   4: #include <QWidget>
   5: #include <qwt_plot_curve.h>
   6: #include <qfile.h>
   7: #include <qwt_plot_magnifier.h>
   8:  
   9: namespace Ui {
  10:     class AdPlot;
  11: }
  12:  
  13: class AdPlot : public QWidget
  14: {
  15:     Q_OBJECT
  16:  
  17: public:
  18:     explicit AdPlot(QWidget *parent = 0);
  19:     //要绘制的AD数据,X-时间,Y-电压值
  20:     void readAdData(QVector< double > &xData,
  21:                     QVector< double > &yData);
  22:     void setTitleString(QString title);
  23:     void setTimerStop();
  24:  
  25:     ~AdPlot();
  26: public slots:
  27:     //节点打开的AD数据的文件名
  28:     void setFileName(QString filename);
  29:     //绘制AD数据
  30:     void plotAdCurve();
  31: private:
  32:     Ui::AdPlot *ui;
  33:     QwtPlotCurve *p_adplot;
  34:     QVector< double > xData;
  35:     QVector< double > yData;
  36:     QFile *localFile;
  37:     //文件偏移量
  38:     qint64 offset;
  39:     double time;
  40:     QString m_filename;
  41:     QwtPlotMagnifier *PM;
  42:     //当前X轴最大的范围
  43:     int xMaxScale;
  44:  
  45:     QTimer *adPlotTimer;
  46:  
  47:     QString m_title;
  48: };
  49:  
  50: #endif // ADPLOT_H

 

   头文件没什么好说的,说明一下offset这个变量,它是用来保存当前的读取到的文件位置,而xData和yData分别储存时间和电压值。

“AdPlot.cpp”

   1: #include "adplot.h"
   2: #include "ui_adplot.h"
   3: #include <QtGui/QApplication>
   4: #include <qapplication.h>
   5: #include <qlayout.h>
   6: #include <qlabel.h>
   7: #include <qpainter.h>
   8: #include <qwt_plot_layout.h>
   9: #include <qwt_plot_curve.h>
  10: #include <qwt_scale_draw.h>
  11: #include <qwt_scale_widget.h>
  12: #include <qwt_legend.h>
  13: #include <qwt_legend_item.h>
  14: #include <QTime>
  15: #include <qtimer.h>
  16: #include <QMessageBox>
  17: #include <qcolor.h>
  18: #include <qwt_plot_zoomer.h>
  19:  
  20: class TimeScaleDraw: public QwtScaleDraw
  21: {
  22: public:
  23:     TimeScaleDraw(const QTime &base):
  24:         baseTime(base)
  25:     {
  26:     }
  27:  
  28:     virtual QwtText label(double v) const
  29:     {
  30:         QTime upTime = baseTime.addSecs((int)v);
  31:         return upTime.toString();
  32:     }
  33:  
  34: private:
  35:     QTime baseTime;
  36: };
  37:  
  38:  
  39: AdPlot::AdPlot(QWidget *parent) :
  40:     QWidget(parent),
  41:     ui(new Ui::AdPlot)
  42: {
  43:     ui->setupUi(this);
  44:     ui->qwtPlot->setAutoReplot(false);
  45:     QTime curTime;
  46:     curTime = curTime.currentTime();
  47:  
  48:  
  49:  
  50:     QwtLegend *legend = new QwtLegend;
  51:     legend->setItemMode(QwtLegend::CheckableItem);
  52:     //ui->qwtPlot->insertLegend(legend, QwtPlot::RightLegend);
  53:     ui->qwtPlot->setAxisTitle(QwtPlot::xBottom, " System Uptime [h:m:s]");
  54:     ui->qwtPlot->setAxisScaleDraw(QwtPlot::xBottom,
  55:         new TimeScaleDraw(curTime));
  56:     ui->qwtPlot->setAxisScale(QwtPlot::xBottom, 0, xMaxScale = 5);
  57:     ui->qwtPlot->setAxisLabelAlignment(QwtPlot::xBottom, Qt::AlignLeft | Qt::AlignBottom);
  58:  
  59:     QwtScaleWidget *scaleWidget = ui->qwtPlot->axisWidget(QwtPlot::xBottom);
  60:     const int fmh = QFontMetrics(scaleWidget->font()).height();
  61:     scaleWidget->setMinBorderDist(0, fmh / 2);
  62:  
  63:     ui->qwtPlot->setAxisTitle(QwtPlot::yLeft, "V");
  64:     ui->qwtPlot->setAxisScale(QwtPlot::yLeft, 0, 3);
  65:     p_adplot = new QwtPlotCurve();
  66:     QColor c = Qt::red;
  67:     c.setAlpha(150);
  68:     p_adplot->setPen(c);
  69:  
  70:     p_adplot->attach(ui->qwtPlot);
  71:     //PM = new QwtPlotMagnifier(ui->qwtPlot->canvas());
  72:     QwtPlotZoomer* zoomer = new QwtPlotZoomer( ui->qwtPlot->canvas() );
  73:     zoomer->setRubberBandPen( QColor( Qt::black ) );
  74:     zoomer->setTrackerPen( QColor( Qt::black ) );
  75:     zoomer->setMousePattern(QwtEventPattern::MouseSelect2,Qt::RightButton, Qt::ControlModifier );
  76:     zoomer->setMousePattern(QwtEventPattern::MouseSelect3,Qt::RightButton );
  77:     time = 0.0;
  78:     adPlotTimer = new QTimer();
  79:     adPlotTimer->start(100);
  80:     connect(adPlotTimer, SIGNAL(timeout()),
  81:             this, SLOT(plotAdCurve()));
  82:     offset = 0;
  83: }
  84:  
  85: AdPlot::~AdPlot()
  86: {
  87:     delete ui;
  88: }
  89:  
  90: void AdPlot::readAdData(QVector<double> &xData, QVector<double> &yData)
  91: {
  92:     if(!m_filename.isEmpty())
  93:     {
  94:         localFile = new QFile(m_filename); //用户端的IP地址+端口号作为文件名
  95:         if (!localFile->open(QFile::ReadOnly ))
  96:         {
  97:             QMessageBox::warning(0, tr("应用程序"),
  98:                                     tr("无法读取文件 %1:\n%2.")
  99:                                     .arg(m_filename)
 100:                                     .arg(localFile->errorString()));
 101:             return;
 102:         }
 103:         QByteArray adData;
 104:         if (!localFile->atEnd())
 105:         {
 106:             if (offset == 0)
 107:             {
 108:                 adData = localFile->read(26);
 109:                 qDebug()<<adData;
 110:                 offset += 26;
 111:                 adData.resize(0);
 112:                 return;
 113:             }
 114:  
 115:             if (localFile->seek(offset))
 116:             {
 117:  
 118:                 adData = localFile->read(32*2);
 119:                 if (adData.count() == 32*2)
 120:                 {
 121:                     for (int count=0; count<32; count++)
 122:                     {
 123:                         char lowbits = adData.at(count*2);
 124:                         char highbits = adData.at(count*2 + 1);
 125:                         short temp = lowbits+highbits*256;
 126:                         yData.append(((float)temp)*3300/4096/1000);
 127:                         xData.append(time);
 128:                         time += 0.005;  //5ms一个数据
 129:                     }
 130:                     offset += 32*2;
 131:                 }
 132:             }
 133:         }
 134:     }
 135:  
 136: }
 137:  
 138: void AdPlot::plotAdCurve()
 139: {
 140:     readAdData(xData,yData);
 141:     p_adplot->setSamples(xData,yData);
 142:     if (!xData.empty())
 143:     {
 144:         if (xData.last() >= xMaxScale)
 145:         {
 146:             xMaxScale *= 2;
 147:             ui->qwtPlot->setAxisScale(QwtPlot::xBottom, 0, xMaxScale);
 148:         }
 149:     }
 150:     p_adplot->attach(ui->qwtPlot);
 151:     ui->qwtPlot->replot();
 152:     adPlotTimer->start(100);
 153:  
 154:  
 155: }
 156:  
 157: void AdPlot::setFileName(QString filename)
 158: {
 159:     m_filename = filename;
 160: }
 161:  
 162: void AdPlot::setTitleString(QString title)
 163: {
 164:     m_title = title;
 165:     ui->qwtPlot->setTitle(m_title);
 166: }
 167:  
 168: void AdPlot::setTimerStop()
 169: {
 170:     adPlotTimer->stop();
 171: }

首先:

说一下TimeScaleDraw这个类,它继承了QwtScaleDraw的类,其实就是一个抽象的一个刻度类,具体的函数说明可以参考说明手册.

对了,ui界面里没什么东西,就一个qwtplot的控件image.

 

接着初始化坐标轴:

  1. void setAxisTitle(int axisId, const QString &)用来设置坐标轴名字,第一个参数是QWT定义的坐标轴ID,即yLeft,yRight,xBottomxTop.
  2. void setAxisScaleDraw(int axisId, QwtScaleDraw*)用来设置坐标轴刻度,第一个参数同上,第二个参数就是我们刚才定义的TimeScaleDraw;
  3. void setAxisScale(int axisId, double min, double max, doublestep=0)也是设置刻度的,第一个参数同上,第二参数是刻度的最小值,第三个参数是刻度的最大值,最后一个是步长.

 

然后定义一个曲线QwtPlotCurve:

    QwtPlotCurve,它的功能就是输入一系列的X,Y的值,然后绘制出曲线,当然,曲线的color,style那些是可以自己设置的.

 

缩放曲线(PS:这点就体现了QWT的强大之处):

    QwtPlotZoomer,简单的一个类,简单的只个设置就可以缩放曲线,谁用谁知道啊.

 

定时器完成曲线的重绘:

     adPlotTimer = new QTimer();

     adPlotTimer->start(100);

     connect(adPlotTimer, SIGNAL(timeout()), this,SLOT(plotAdCurve()));

     因为所用的AD是400K的,算了一下,大概160ms以下就能满足了.

 

读取AD数据:

    因为服务器接收到的AD数据是保存在文件中的,而且是实时保存(也就是将Client接收的数据保存到文件的同时将此文件中的数据绘制出来).所以设置了一个文件偏移量,而已此文件的前26字节是采集的时间信息,所以跳过.

    又因为用的是AD是12位的,Client采用一个short类型来保存数据,而已每次传输32个AD数据,所以在计算AD数据前要确保文件已经有了32个AD数据,即64字节的数据.

 

绘制AD数据:

    void setSamples(const QVector< double >&xData, const QVector< double> &yData)完成数据的设置.

    此函数重点在于时间轴的拉长:

    if (xData.last() >= xMaxScale)

        {
            xMaxScale *= 2;
            ui->qwtPlot->setAxisScale(QwtPlot::xBottom, 0, xMaxScale);
        }
 

总结:

    qwt的确一个优秀的第三方库,使用也不复杂,而已有详细的文档说明,还有很多例子,不过都是英文的,慢慢看吧.

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值