最近项目中遇到的一个需求是关于用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
#include
#include
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
#include
#include
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()< 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()<errorString(); // }}其中的结构体是单独的一个文件thetestdata.h放在和发送端的头文件和源文件相同的目录中:
#ifndef THETESTDATA_H#define THETESTDATA_H#pragma pack(1)#ifndef _MASSEGE_HEADER#define _MASSEGE_HEADERtypedef 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_DATAtypedef 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 networkCONFIG += qwtDEFINES += QT_DLL QWT_DLLLIBS += -L"D:\build-qwt-Desktop_Qt_5_6_3_MSVC2013_64bit-Debug\lib" -lqwtdLIBS += -L"D:\build-qwt-Desktop_Qt_5_6_3_MSVC2013_64bit-Debug\lib" -lqwtINCLUDEPATH += F:\Qt\Qt5.6.3\5.6.3\msvc2013_64\include\QWTgreaterThan(QT_MAJOR_VERSION, 4): QT += widgetsTARGET = UdpClientTEMPLATE = appSOURCES += main.cpp\clientwidget.cpp
HEADERS += clientwidget.hFORMS += clientwidget.ui头文件如下:
#ifndef CLIENTWIDGET_H#define CLIENTWIDGET_H#include#include#include#include#include#include#include#include#include#include#include#include#include#include#include#include#includenamespace Ui {class ClientWidget;}class ClientWidget : public QWidget{Q_OBJECTpublic:
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#include#include#include "thetestdata.h"#includeClientWidget::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()< 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();
}其中结构体文件和发送端一样也是放在与接收端的源文件一个目录。
其显示的效果如下: