关于QUdpSocket和Qwt动态曲线的小例子

        最近项目中遇到的一个需求是关于用udp接收数据来显示一个动态曲线,觉得以后可能还会遇到于是写一个小例子记录一下。废话不多说直接贴代码。

        首先是数据发送端:

新建一个Qt Widgets Application,选择Qwidget,其中工程文件如下:

其中主要是QudpSocket的使用其他没什么可说的。

#-------------------------------------------------
#
# Project created by QtCreator 2018-06-07T19:21:13
#
#-------------------------------------------------
 
 
QT       += core gui network
 
 
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
 
 
TARGET = QUdpServer
TEMPLATE = app
 
 
 
 
SOURCES += main.cpp\
        widgetserver.cpp
 
 
HEADERS  += widgetserver.h \
#    thetestdata.h
 
 
FORMS    += widgetserver.ui
 
 

头文件如下:

#ifndef WIDGETSERVER_H
#define WIDGETSERVER_H
 
 
#include <QWidget>
#include <QUdpSocket>
#include <QDebug>
 
 
namespace Ui {
class WidgetServer;
}
 
 
class WidgetServer : public QWidget
{
    Q_OBJECT
 
 
public:
    explicit WidgetServer(QWidget *parent = 0);
    ~WidgetServer();
private slots:
    void on_pushButton_send_clicked();
    void time_out_Slot();
private:
    void initSorket();
private:
    Ui::WidgetServer *ui;
    QUdpSocket* sender;
    QTimer*     timer;
};
 
 
#endif // WIDGETSERVER_H
 
 

源文件:

#include "widgetserver.h"
#include "ui_widgetserver.h"
#include "thetestdata.h"
#include <QDebug>
#include <QTime>
#include <QTimer>
WidgetServer::WidgetServer(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::WidgetServer)
{
    ui->setupUi(this);
    timer = new QTimer(this);
    timer->start(1000);
    initSorket();
    connect(timer, SIGNAL(timeout()), this, SLOT(time_out_Slot()));
 
 
}
 
 
WidgetServer::~WidgetServer()
{
    delete ui;
}
//初始化QUdpSocket
void WidgetServer::initSorket()
{
    sender = new QUdpSocket(this);
    sender->bind(QHostAddress::Broadcast, 7755);
}
 
 
void WidgetServer::on_pushButton_send_clicked()
{
 
 
}
//时间槽函数 并对数据进行赋值发送
void WidgetServer::time_out_Slot()
{
    Massege_Data msg;
    int msg_length = sizeof(Massege_Data);
    qDebug()<<msg_length;
    memset(&msg,0,sizeof(Massege_Data));
    msg.massege_header.massege_header = 1001;
    msg.massege_header.msg_num = 1;
    msg.test_data1 = 1;
    msg.test_data2 = 2;
    msg.massege_header.massege_length_uh = sizeof(Massege_Data);
 
 
    qsrand(QTime(0,0,0).secsTo(QTime::currentTime()));
    for(int i=0 ; i< 100;++i)
    {
        msg.the_y[i]= qrand()%90;
    }
 
 
    sender->writeDatagram((char*)&msg,sizeof(Massege_Data),QHostAddress::LocalHost,7755);
 
 
    //    qreal xy = sender->write((char*)&msg,sizeof(Massege_Data));
    //    if(xy==-1)
    //    {
    //        qDebug()<<sender->errorString();
    //    }
}
 
 

其中的结构体是单独的一个文件thetestdata.h放在和发送端的头文件和源文件相同的目录中:

#ifndef THETESTDATA_H
#define THETESTDATA_H
#pragma pack(1)
#ifndef _MASSEGE_HEADER
#define _MASSEGE_HEADER
typedef struct MassegeHeader{
    unsigned short int massege_header;//消息头
    unsigned short int massege_length_uh;//消息长度
    unsigned short int msg_num;//包数号
    unsigned short int msg_num_all;//总包数
    unsigned int       time_e;//时间戳
    unsigned char      spare_uc[9];//消息源
    unsigned char      bak[3];
 
 
}MassegeHeader;
#endif
 
 
#ifndef _MAGGEGE_DATA
#define _MAGGEGE_DATA
typedef struct Massege_Data{
    MassegeHeader         massege_header;
    unsigned short int    test_data1;
    unsigned short int    test_data2;
    unsigned short int    the_y[100];
}Massege_Data;
#endif
 
 
#pragma pack()
#endif // THETESTDATA_H
 
 

接下来是接收端也是新建Qt Widgets Application,选择Qwidget,要稍微复杂一点的就是重写了Qwt:

其界面如图:

其工程文件如下:

#-------------------------------------------------
#
# Project created by QtCreator 2018-06-09T20:57:32
#
#-------------------------------------------------
 
 
QT       += core gui network
 
 
CONFIG += qwt
DEFINES += QT_DLL QWT_DLL
 
 
LIBS += -L"D:\build-qwt-Desktop_Qt_5_6_3_MSVC2013_64bit-Debug\lib" -lqwtd
LIBS += -L"D:\build-qwt-Desktop_Qt_5_6_3_MSVC2013_64bit-Debug\lib" -lqwt
INCLUDEPATH += F:\Qt\Qt5.6.3\5.6.3\msvc2013_64\include\QWT
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
 
 
TARGET = UdpClient
TEMPLATE = app
 
 
 
 
SOURCES += main.cpp\
        clientwidget.cpp
 
 
HEADERS  += clientwidget.h
 
 
FORMS    += clientwidget.ui
 
 

头文件如下:

#ifndef CLIENTWIDGET_H
#define CLIENTWIDGET_H
#include <QWidget>
#include <qmath.h>
#include <QVector>
#include <qwt_plot.h>
#include <qwt_plot_curve.h>
#include <qwt_plot_magnifier.h>
#include <qwt_plot_panner.h>
#include <qwt_legend.h>
#include <qwt_point_data.h>
#include <qwt_plot_grid.h>
#include <qwt_plot_picker.h>
#include <qwt_picker.h>
#include <QColor>
#include <QDebug>
#include <QUdpSocket>
#include <QPen>
#include <QTimer>
namespace Ui {
class ClientWidget;
}
 
 
class ClientWidget : public QWidget
{
    Q_OBJECT
 
 
public:
    explicit ClientWidget(QWidget *parent = 0);
    ~ClientWidget();
    //设置画布标题
    void setPlotTitle(const QString &strTitle);
    //重绘
    void reDraw();
    //设置x轴,y轴信息
    void setAxisTitles(QwtPlot::Axis asixId,const QString &strText);
    //设置x,y的值
    void setAxisRange(QwtPlot::Axis asixId,const double dStart,const double dEnd,const double dIndex=0.0);
    //创建网格
    QwtPlotGrid* createGrid();
    //获取网格
    QwtPlotGrid* getGrid();
    //设置是否显示
    void setGridIsShow(QwtPlot::Axis asixId,bool show);
    //设置网格类型和颜色
    void setGridColor(QColor color,qreal qrlinewidth,Qt::PenStyle ePenStyle);
    //创建曲线
    QwtPlotCurve* createCurve();
    //设置曲线是否显示
    void setCurveIsShow(QwtPlotCurve* pCurve,bool show);
    //删除曲线
    void delCurve(QwtPlotCurve* pCurve);
    //设置曲线数据和颜色
    void setCurveData(QwtPlotCurve* pCurve, QwtPointArrayData * const data,QPen pen);
 
 
    void addItem(int ixPos,int iYPos,const QwtText &qwtText);
    void delItem(QwtPlotItem *plotItem);
    void setItemPos(QwtPlotItem *plotItem,int ixPos,int iyPos);
    void setItemIsShow(QwtPlotItem *plotItem,bool show);
    void setTipMsg(QPoint pos,QString strText);
protected:
    void resizeEvent(QResizeEvent* re);
 
 
private slots:
    void on_pushButton_clicked();
    void readPendingDatagrams();
    void time_out_Slot();
private:
    Ui::ClientWidget *ui;
    QList<QwtPlotCurve*> m_listCurve;
    QList<QwtPlotItem*>  m_listItem;
    QwtPlotGrid *m_plotGrid;
    QwtPlot*     m_plot;
    QwtPlotPicker * m_picker;
    double  m_dXStart,m_dYStart,m_dXEnd,m_dYEnd;
    QUdpSocket* recvUdpSocket;
    QwtPlotCurve* testCurve;
    QwtPlotCurve* Msg_Udp_Curve;
    QTimer *timer;
};
 
 
#endif // CLIENTWIDGET_H
 
 

源文件如下:

#include "clientwidget.h"
#include "ui_clientwidget.h"
#include <QFont>
#include <QPolygonF>
#include <QResizeEvent>
#include "thetestdata.h"
#include <QTime>
ClientWidget::ClientWidget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::ClientWidget)
{
    ui->setupUi(this);
    m_plot = NULL;
    m_plot = ui->plot;
    m_plotGrid = NULL;
    createGrid();
    m_listCurve.clear();
    m_listItem.clear();
    m_picker = new QwtPlotPicker(QwtPlot::xBottom,QwtPlot::yLeft,
                                  QwtPicker::PolygonRubberBand,
                                  QwtPicker::AlwaysOn,m_plot->canvas());
    m_picker->setRubberBandPen(QColor(Qt::green));
    m_picker->setRubberBand(QwtPicker::CrossRubberBand);
    m_picker->setTrackerPen(QColor(Qt::black));
    (void) new QwtPlotMagnifier(m_plot->canvas());
     (void) new QwtPlotPanner( m_plot->canvas() );
    recvUdpSocket = new QUdpSocket(this);
    recvUdpSocket->bind(QHostAddress::LocalHost, 7755);
 
 
    connect(recvUdpSocket, SIGNAL(readyRead()),
                  this, SLOT(readPendingDatagrams()));
    timer = new QTimer(this);
    timer->start(1000);
 
 
    //connect(timer, SIGNAL(timeout()), this, SLOT(time_out_Slot()));
    testCurve = NULL;
    testCurve = createCurve();
    Msg_Udp_Curve = NULL;
    Msg_Udp_Curve = createCurve();
 
 
}
 
 
ClientWidget::~ClientWidget()
{
    delete ui;
}
 
 
void ClientWidget::setPlotTitle(const QString &strTitle)
{
    QwtText qwtText = QwtText(strTitle);
    qwtText.setFont(QFont("Bitstream Charter",12,50,false));
    m_plot->setTitle(qwtText);
}
 
 
void ClientWidget::reDraw()
{
 
 
    m_plot->replot();
//    m_plot->detachItems();
}
 
 
void ClientWidget::setAxisTitles(QwtPlot::Axis asixId, const QString &strText)
{
    QwtText qwtText = QwtText(strText);
    qwtText.setFont(QFont("Bitstream Charter",9,50,false));
    m_plot->setAxisTitle(asixId,qwtText);
}
 
 
void ClientWidget::setAxisRange(QwtPlot::Axis asixId, const double dStart, const double dEnd, const double dIndex)
{
    m_plot->setAxisScale(asixId,dStart,dEnd,dIndex);
    if(asixId==QwtPlot::xBottom)
    {
        m_dXStart = dStart;
        m_dXEnd   = dEnd;
    }
    else if (asixId==QwtPlot::yLeft)
    {
        m_dYStart = dStart;
        m_dYEnd   = dEnd;
    }
}
 
 
QwtPlotGrid *ClientWidget::createGrid()
{
    if(m_plotGrid != NULL) return m_plotGrid;
    m_plotGrid = new QwtPlotGrid;
    setGridColor(Qt::gray,0.0,Qt::DotLine);
    m_plotGrid->attach(m_plot);
}
 
 
QwtPlotGrid *ClientWidget::getGrid()
{
    return m_plotGrid;
}
 
 
void ClientWidget::setGridIsShow(QwtPlot::Axis asixId, bool show)
{
    if(m_plotGrid == NULL) return;
    if(asixId == QwtPlot::xBottom)
        m_plotGrid->enableX(show);
    else if(asixId == QwtPlot::yLeft)
        m_plotGrid->enableY(show);
}
 
 
void ClientWidget::setGridColor(QColor color, qreal qrlinewidth, Qt::PenStyle ePenStyle)
{
    if(m_plotGrid == NULL) return;
    m_plotGrid->setPen(QPen(color,qrlinewidth,ePenStyle));
}
 
 
QwtPlotCurve *ClientWidget::createCurve()
{
    QwtPlotCurve* pCurve = new QwtPlotCurve();
    pCurve->setRenderHint(QwtPlotItem::RenderAntialiased);
    m_listCurve.append(pCurve);
    pCurve->attach(m_plot);
    return pCurve;
}
 
 
void ClientWidget::setCurveIsShow(QwtPlotCurve *pCurve, bool show)
{
    if(show)
    {
        if(!m_listCurve.contains(pCurve))
            m_listCurve.append(pCurve);
        pCurve->attach(m_plot);
    }
    else
    {
        pCurve->detach();
    }
}
 
 
void ClientWidget::delCurve(QwtPlotCurve *pCurve)
{
    if(m_listCurve.contains(pCurve)) return;
    m_listCurve.removeOne(pCurve);
    pCurve->detach();
    delete pCurve;
    pCurve = NULL;
}
 
 
void ClientWidget::setCurveData(QwtPlotCurve *pCurve,QwtPointArrayData * const data, QPen pen)
{
    if(pCurve != NULL)
        pCurve->setData(data);
    pCurve->setPen(pen);
}
 
 
void ClientWidget::addItem(int ixPos, int iYPos, const QwtText &qwtText)
{
 
 
}
 
 
void ClientWidget::delItem(QwtPlotItem *plotItem)
{
 
 
}
 
 
void ClientWidget::setItemPos(QwtPlotItem *plotItem, int ixPos, int iyPos)
{
 
 
}
 
 
void ClientWidget::setItemIsShow(QwtPlotItem *plotItem, bool show)
{
 
 
}
 
 
void ClientWidget::setTipMsg(QPoint pos, QString strText)
{
 
 
}
 
 
void ClientWidget::resizeEvent(QResizeEvent *re)
{
    int w = re->size().width();
    QWidget::resizeEvent(re);
}
 
 
void ClientWidget::on_pushButton_clicked()
{
    timer->stop();
}
 
 
void ClientWidget::readPendingDatagrams()
{
    Massege_Data msg;
    memset(&msg,0,sizeof(Massege_Data));
    while (recvUdpSocket->hasPendingDatagrams()) {
            QByteArray datagram;
            QHostAddress sender = QHostAddress::LocalHost;
            quint16 senderPort = 7755;
            datagram.resize(recvUdpSocket->pendingDatagramSize());
            recvUdpSocket->readDatagram((char*)&msg, sizeof(Massege_Data),
                                    &sender,&senderPort);
        }
 
 
        QVector<double> xs;
        QVector<double> ys;
        for (int i=0;i<100;++i)
        {
            ys.append(msg.the_y[i]);
            xs.append(i);
        }
        //构造曲线数据
        QwtPointArrayData * const data = new QwtPointArrayData(xs, ys);
//
 
 
        setAxisRange(QwtPlot::xBottom,0,100);
        setAxisRange(QwtPlot::yLeft,0,100);
        setAxisTitles(QwtPlot::xBottom,"x__");
        setAxisTitles(QwtPlot::yLeft,QString("y__"));
 
 
        setCurveData(Msg_Udp_Curve,data,QPen(Qt::blue));
        reDraw();
}
 
 
void ClientWidget::time_out_Slot()
{
    if(testCurve != NULL)
        delCurve(testCurve);
    Massege_Data msg_test;
    int msg_length = sizeof(Massege_Data);
    qDebug()<<msg_length;
    memset(&msg_test,0,sizeof(Massege_Data));
    msg_test.massege_header.massege_header = 1001;
    msg_test.massege_header.msg_num = 1;
 
 
    qsrand(QTime(0,0,0).secsTo(QTime::currentTime()));
    for(int i=0 ; i< 100;++i)
    {
           msg_test.the_y[i] = qrand()%90;
    }
    QVector<double> xs;
    QVector<double> ys;
    for (int i=0;i<100;++i)
    {
        ys.append(msg_test.the_y[i]);
        xs.append(i);
    }
    //构造曲线数据
    QwtPointArrayData * const data = new QwtPointArrayData(xs, ys);
    setAxisRange(QwtPlot::xBottom,0,100);
    setAxisRange(QwtPlot::yLeft,0,100);
 
 
 
 
    setCurveData(testCurve,data,QPen(Qt::red));
    reDraw();
 
 
}
 
 

其中结构体文件和发送端一样也是放在与接收端的源文件一个目录。

其显示的效果如下:


猜你喜欢

转载自blog.csdn.net/yang1993617/article/details/80653949
qwt
今日推荐