当前位置: 首页 > news >正文

QT学习之旅 - 一个QT的基本项目

文章目录

      • 定时器(时间)
      • 位置信息
      • QTableWidget用cellwidget添加控件
        • 隐藏QTableWidget的滚动条
        • 自动调整适应大小
      • UDP
        • UDP Client
        • UDP Server
        • UDP udpSocket.readDatagram
        • 重要参数
        • 使用多线程udp
      • 自定义信号和槽
        • UDP服务端接收数据(全局变量)
      • QWT
        • 设置标题
        • 数轴相关
          • 设置坐标轴范围
          • 设置坐标轴备注
          • 设置坐标轴数值的字体
        • 添加数据
          • 曲线图
            • 注意点
          • 直方图
        • 设置网格
        • 左键选中放大,右键恢复上级,CTRL+右键恢复原样
        • 显示图标(一): QwtLegend
        • 显示图标(二): QwtPlotLegendItem
        • QWT + FFT
      • 字符串截取
      • 进制转换
        • QString转int
        • QString转QByteArray(16进制)
        • QByteArray(16进制)转float
        • 字符串转float
        • Qhostaddress 与 Qstring互转
        • 2个uint8_t拼接
        • 3个uint8_t拼接
      • 响应式控件改变位置
      • Qt:cannot open output file debug\XXX.exe: Permission denied
      • 类型断言
        • 静态类型断言
        • reinterpret_cast

定时器(时间)

//TitleDialogOne.cpp
//用new的方式创建一个QTimer对象
timer = new QTimer(this); //QTimer *timer;
//将定时器的溢出信号连接到自定义的槽函数。
connect(timer,&QTimer::timeout,this,&TitleDialogOne::onNowTimeOut);
timer->start(1000);
//TitleDialogOne.cpp
void TitleDialogOne::onNowTimeOut(){QString dt = QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss");ui->labelNowTime->setText(dt);
}

位置信息

QTableWidget用cellwidget添加控件

//单元格添加样式
ui->tableWidgetTop->setCellWidget(0, 1, new QSpinBox);//单元格读取
getTop1 = (QSpinBox *)ui->tableWidgetTop->cellWidget(0,1);//QSpinBox* getTop1;//#define TOP_CHL_COUNT         (16)      /* 通道数量 */
getTop1->setRange(0,TOP_CHL_COUNT); //设置可选范围
getTop1->setValue(5); //设置初始值为5

隐藏QTableWidget的滚动条

ui->tableWidget->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);//隐藏横向滚动条
ui->tableWidget->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);//隐藏纵向滚动条

自动调整适应大小

ui->tableWidgetTop->horizontalHeader()->setSectionResizeMode(0, QHeaderView::ResizeToContents);
ui->tableWidgetTop->horizontalHeader()->setStretchLastSection(true);

UDP

UDP Client

// QUdpSocket *myUdpSocket;//UDP套接字对象
// QHostAddress myGroupAddress;//组播地址
myUdpSocket = new QUdpSocket;//初始化socket
myGroupAddress.setAddress("239.2.2.222");//设置组播地址
myUdpSocket->bind(8080);//绑定端口号
if(myType == 2){ //myType: 只是一个int类型的变量,来区分是单播(一对一)还是多播(组播,一对多)//组播的数据的生存期,数据报没跨1个路由就会减1.表示多播数据报只能在同一路由下的局域网内传播myUdpSocket->setSocketOption(QAbstractSocket::MulticastTtlOption,1);
}

使用定时器每个1秒发送

void UDPClient::InitTimer(){myTimer = new QTimer;//初始化定时器connect(myTimer,&QTimer::timeout,this,[=]{SendData();});myTimer->start(1000);//开启定时器,每1秒发送一次数据
}
//发送
void UDPClient::SendData(){QByteArray _data = "hello";if(myType == 0){//单播QHostAddress _peerHostAddress = QHostAddress("my_test_ip");//对位服务器IPquint16 _port = my_test_port;//对位服务器端口(int)if(-1 !=myUdpSocket->writeDatagram(_data.data(),_data.size(),_peerHostAddress,_port)){qDebug()<< "单播 ==> Send data : "<< _data<<endl;}myUdpSocket->flush();}else if(myType == 1){ //广播quint16 _port = project_port;//广播端口(int)if(-1 !=myUdpSocket->writeDatagram(_data.data(),QHostAddress::Broadcast,_port)){qDebug()<< "广播 ==> Send data : "<< _data<<endl;}myUdpSocket->flush();}else if(myType == 2){//组播quint16 _port = project_port;//组播端口(int)if(-1 != myUdpSocket->writeDatagram(_data.data(),myGroupAddress,_port)){qDebug()<< "组播 ==> Send data : "<< _data<<endl;}myUdpSocket->flush();}else{qDebug() << "mType is error! "<<endl;return;}
}
  • 单播(一对一): 需要获取服务端的ip和端口号
    • myUdpSocket->writeDatagram写入成功后可以输出查看值
  • 广播(一对所有的通信方式):确认服务端端口发起请求
    • myUdpSocket->writeDatagram写入成功后可以输出查看值
  • 多播(组播,一对多): 需要获取服务端的端口号发起请求
    • myUdpSocket->writeDatagram写入成功后可以输出查看值

UDP Server

void UDPServer::InitSocket()
{//初始化socket,设置组播地址mUdpSocket = new QUdpSocket;mGroupAdress.setAddress(project_zubo_address);if(mType == 0 || mType == 1){//绑定本地IP和端口号mUdpSocket->bind(my_test_server_port);}else if(mType == 2){if(mUdpSocket->bind(QHostAddress::AnyIPv4,my_test_server_port,QUdpSocket::ShareAddress)){//加入组播地址mUdpSocket->joinMulticastGroup(mGroupAdress);qDebug()<<("Join Multicast Adrress [")<<mGroupAdress.toString()<<("] Successful!")<<endl;}}else{qDebug()<< "mType is error! "<<endl;return;}connect(mUdpSocket,&QUdpSocket::readyRead,this,[=]{ReadPendingDataframs();});
}void UDPServer::ReadPendingDataframs()
{QByteArray _data;_data.resize(mUdpSocket->pendingDatagramSize());if(mType == 0)//Unicast{QHostAddress *_peerHostAddress = new QHostAddress(my_test_ip);quint16 _port = my_test_port;while(mUdpSocket->hasPendingDatagrams()){mUdpSocket->readDatagram(_data.data(),_data.size(),_peerHostAddress,&_port);//接收指定IP和端口的udp报文qDebug()<<"Unicast ==> Receive data : "<<QString::fromLatin1(_data)<<endl;}}else if(mType == 1)//Broadcast{QHostAddress _peerHostAddress;quint16 _port;while(mUdpSocket->hasPendingDatagrams()){mUdpSocket->readDatagram(_data.data(),_data.size(),&_peerHostAddress,&_port);//接收同一子网的udp报文qDebug()<<"Broadcast ==> Receive data : "<<QString::fromLatin1(_data)<<endl;}}else if(mType == 2)//Multicast{QHostAddress _peerHostAddress;quint16 _port;while(mUdpSocket->hasPendingDatagrams()){mUdpSocket->readDatagram(_data.data(),_data.size(),&_peerHostAddress,&_port);//接收同组的udp报文qDebug()<<"Multicast ==> Receive data : "<<QString::fromLatin1(_data)<<endl;}}else{qDebug()<< "mType is error! "<<endl;return;}
}

UDP udpSocket.readDatagram

udpSocket.hasPendingDatagrams()

在这里插入图片描述
QUdpSocket类的readDatagram()函数用于从UDP套接字中读取数据报。它的函数原型如下:

QHostAddress QUdpSocket::readDatagram(char *data, qint64 maxSize, QHostAddress *address = nullptr, quint16 *port = nullptr)

参数解释:

  • data:指向用于存储接收数据的缓冲区的指针。
  • maxSize:缓冲区的最大大小,即可以接收的最大数据量。
  • address:可选参数,用于返回发送方的IP地址。
  • port:可选参数,用于返回发送方的端口号。

使用readDatagram()函数可以将接收到的数据存储到指定的缓冲区中,并返回接收到的数据大小。以下是一个示例:

QUdpSocket udpSocket;// 绑定到指定的IP地址和端口
udpSocket.bind(QHostAddress::Any, 1234);// 监听是否有数据可读
QObject::connect(&udpSocket, &QUdpSocket::readyRead, [&udpSocket]() {while (udpSocket.hasPendingDatagrams()) {QByteArray datagram;datagram.resize(udpSocket.pendingDatagramSize());QHostAddress senderAddress;quint16 senderPort;// 读取数据报udpSocket.readDatagram(datagram.data(), datagram.size(), &senderAddress, &senderPort);// 处理接收到的数据QString receivedData = QString::fromUtf8(datagram);qDebug() << "Received data:" << receivedData;qDebug() << "Sender address:" << senderAddress.toString();qDebug() << "Sender port:" << senderPort;}
});

在上面的代码中,我们创建了一个QUdpSocket对象,并使用bind()函数将其绑定到任意IP地址和端口1234。然后,使用readyRead信号来监听是否有数据可读。当有数据可读时,通过readDatagram()函数读取数据,并将其转换为QString类型进行处理。同时,还可以获取发送方的IP地址和端口号。这样,您就可以使用readDatagram()函数在Qt中监听UDP套接字接收到的数据了。

重要参数

// QUdpSocket *mUdpSocket;//UDP套接字对象
// QHostAddress mGroupAddress;//组播地址
mUdpSocket = new QUdpSocket; //实例化对象
mGroupAdress.setAddress("project_zubo_address");//确认组播的地址mUdpSocket->bind(my_test_server_port);//绑定本地IP和端口号
mUdpSocket->bind(QHostAddress::AnyIPv4,my_test_server_port,QUdpSocket::ShareAddress);//绑定IPv4下的组播端口

使用多线程udp

  1. QMutex线程锁
  2. 将信号和槽的udp接收写在run函数中
//#include <QMutex>
//QMutex mutex;
void UdpThread::run(){mutex.lock(); //线程锁connect(udpServer->myUdpSocket,&QUdpSocket::readyRead,this,[=](){while (udpServer->myUdpSocket->hasPendingDatagrams()){//读取数据QByteArray datagram; //16进制datagram.resize(udpServer->myUdpSocket->pendingDatagramSize());udpServer->myUdpSocket->readDatagram(datagram.data(), datagram.size());//数据处理}})mutex.unlock();//线程解锁
}

若对传输速度有要求,就不要用到信号和槽

自定义信号和槽

//自定义信号
#include "signalclass.h"extern QString globalStr;SignalClass::SignalClass()
{
}void SignalClass::setValueSet(const QString& data){emit setValue(data);
}SignalClass::~SignalClass(){}
//自定义槽
#include "slotclass.h"
#include <QDebug>SlotClass::SlotClass()
{}
void SlotClass::slotValue(const QString& data){qDebug() << data;
}SlotClass::~SlotClass(){}
//引用
signalObj = new SignalClass;//SignalClass *signalObj 
slotObj = new SlotClass; //SlotClass *slotObj 
connect(signalObj,&SignalClass::setValue,slotObj,&SlotClass::slotValue);

UDP服务端接收数据(全局变量)

#include "udpserver.h"extern QString globalStr;//这个定义在mainwindow.cpp中const int project_port = 8880;
const QString zubo_address = "239.2.2.222";
const int my_test_server_port = 5500;
const QString my_test_ip = "192.168.1.191";
const int my_test_port = 5500;UDPServer::UDPServer(){myType = 2;InitSocket();
}void UDPServer::InitSocket(){myUdpSocket = new QUdpSocket;myGroupAddress.setAddress(zubo_address);//设置组播地址if(myType == 0||myType == 1){//绑定本地IP和端口号myUdpSocket->bind(my_test_server_port);}else if(myType == 2){if(myUdpSocket->bind(QHostAddress::AnyIPv4,my_test_server_port,QUdpSocket::ShareAddress)){//加入组播地址myUdpSocket->joinMulticastGroup(myGroupAddress);qDebug()<<("Join Multicast Adrress [")<<myGroupAddress.toString()<<("] Successful!")<<endl;}}else{qDebug()<< "mType is error! "<<endl;return;}//事件connect(myUdpSocket,&QUdpSocket::readyRead,this,&UDPServer::ReceiveHexData);
}
void UDPServer::ReceiveStrData(){globalStr = ReadPendingDataframs();qDebug() << "udp-globalUdpMessage:" << globalStr;testSendSetValue(globalStr);
}
void UDPServer::testSendSetValue(const QString &data){//connect(myUdpSocket,&UDPServer::setValue,this,&ConfigDialog::showTextEdit2,Qt::DirectConnection);emit setValue(data);
}
//读取udp传输过来的字符串信息
QString UDPServer::ReadPendingDataframs(){QString buffer;QByteArray _data;_data.resize(myUdpSocket->pendingDatagramSize());if(myType == 0)//Unicast{QHostAddress *_peerHostAddress = new QHostAddress(my_test_ip);quint16 _port = my_test_port;while(myUdpSocket->hasPendingDatagrams()){myUdpSocket->readDatagram(_data.data(),_data.size(),_peerHostAddress,&_port);//接收指定IP和端口的udp报文qDebug()<<"Unicast ==> Receive data : "<<QString::fromLatin1(_data)<<endl;buffer = QString::fromLatin1(_data);}}else if(myType == 1)//Broadcast{QHostAddress _peerHostAddress;quint16 _port;while(myUdpSocket->hasPendingDatagrams()){myUdpSocket->readDatagram(_data.data(),_data.size(),&_peerHostAddress,&_port);//接收同一子网的udp报文qDebug()<<"Broadcast ==> Receive data : "<<QString::fromLatin1(_data)<<endl;buffer = QString::fromLatin1(_data);}}else if(myType == 2)//Multicast{QHostAddress _peerHostAddress;quint16 _port;while(myUdpSocket->hasPendingDatagrams()){myUdpSocket->readDatagram(_data.data(),_data.size(),&_peerHostAddress,&_port);//接收同组的udp报文qDebug()<<"Multicast ==> Receive data : "<<QString::fromLatin1(_data)<<endl;buffer = QString::fromLatin1(_data);}}else{qDebug()<< "mType is error! "<<endl;buffer = "error";}//testSendSetValue(buffer);return buffer;
}
//读取接收到的16进制数
void UDPServer::ReceiveHexData(){ while (myUdpSocket->hasPendingDatagrams()){// 读取数据QByteArray datagram;datagram.resize(myUdpSocket->pendingDatagramSize());myUdpSocket->readDatagram(datagram.data(), datagram.size());// 将数据转换为16进制字符串
//      QString hexData = QString(datagram.toHex());globalStr = QString(datagram.toHex()); //将接收到的16进制数据赋值给权全局变量// 打印16进制数据qDebug() << "udp-Hex-Received data: " << globalStr;}
}UDPServer::~UDPServer(){delete myUdpSocket;
}

在另一个文件(UI文件)中也是connect(myUdpSocket,&QUdpSocket::readyRead,this,&UDPServer::ReceiveHexData);只不过形式变了

//...
extern QString globalStr;//这个定义在mainwindow.cpp中ConfigDialog::ConfigDialog(QWidget *parent) :QWidget(parent),ui(new Ui::ConfigDialog)
{ui->setupUi(this);ui->textEdit_2->setReadOnly(true);//udpudpServer = new UDPServer;connect(udpServer->myUdpSocket,&QUdpSocket::readyRead,this,[=](){ui->textEdit_2->insertPlainText(globalStr += '\n'); //将全局变量中的数据显示出来(udp的接收到的数据)});
}

想法是: 当发生客户端UDP传输去读数据时,在俩个文件(ui文件和udp server)中都发生connect指令

QWT

设置标题

ui->qwtPlot->setTitle(QStringLiteral("这是标题"));

在这里插入图片描述

带属性设置标题

QwtText title;
title.setText(QStringLiteral("属性标题"));// 设置字体 字体大小 加粗 斜体 字体颜色
QFont font;
font.setFamily("Microsoft YaHei UI Light");
font.setPointSize(20);
font.setBold(true);
font.setItalic(true);
title.setFont(font);
//设置字体颜色
title.setColor(Qt::red);
ui->qwtPlot_1->setTitle(title);

数轴相关

ui->qwtPlot->enableAxis(QwtAxis::YLeft,true);      // 左x轴
ui->qwtPlot->enableAxis(QwtAxis::YRight,true);     // 右x轴
ui->qwtPlot->enableAxis(QwtAxis::XTop,true);       // 顶部y轴
ui->qwtPlot->enableAxis(QwtAxis::XBottom,true);    // 底部y轴
设置坐标轴范围
//ui->qwtPlot->setAxisScale(坐标枚举,最小值,最大值,步长);
ui->qwtPlot->setAxisScale(QwtAxis::YLeft,0,50,10);
ui->qwtPlot->setAxisScale(QwtAxis::YRight,0,50,10);
ui->qwtPlot->setAxisScale(QwtAxis::XTop,0,50,10);
ui->qwtPlot->setAxisScale(QwtAxis::XBottom,0,150,30);

在这里插入图片描述

设置坐标轴备注
//ui->qwtPlot->setAxisTitle(坐标枚举,坐标名称);
ui->qwtPlot->setAxisTitle(QwtAxis::YLeft,"YLeft");
ui->qwtPlot->setAxisTitle(QwtAxis::YRight,"YRight");
ui->qwtPlot->setAxisTitle(QwtAxis::XTop,"XTop");
ui->qwtPlot->setAxisTitle(QwtAxis::XBottom,"XBottom");

在这里插入图片描述

设置坐标轴数值的字体
//QFont xtopFont(字体名称,字体大小)
QFont xtopFont("宋体",14);
xtopFont.setBold(true);
xtopFont.setItalic(true);
//ui->qwtPlot->setAxisFont(坐标枚举,QFont)
ui->qwtPlot->setAxisFont(QwtAxis::XTop,xtopFont);

在这里插入图片描述

添加数据

曲线图
//显示那个方位的坐标
ui->qwtPlot->enableAxis(QwtAxis::YLeft,true);      // 左x轴
ui->qwtPlot->enableAxis(QwtAxis::XBottom,true);    // 底部y轴
//设置坐标范围和步长
ui->qwtPlot->setAxisScale(QwtAxis::YLeft,0,10,1);
ui->qwtPlot->setAxisScale(QwtAxis::XBottom,0,10,1);//添加数据(重点)
QwtPlotCurve *plotCurve = new QwtPlotCurve();//#include "qwt_plot_curve.h"
plotCurve->setCurveAttribute(QwtPlotCurve::Fitted);
double time[10]={1,2,3,4,5,6,7,8,9,10};
double val[10]={3, 5, 8, 7, 2, 0, 7, 9, 1,10};
//plotCurve->setSamples(x,y,x-valueNumber);(重点)
plotCurve->setSamples(time,val,5);
plotCurve->setStyle(QwtPlotCurve::CurveStyle::Lines);
//显示到控件上(重点)
plotCurve->attach(ui->qwtPlot);

在这里插入图片描述

注意点

使用setSamples的时候如果你的x轴数组<y轴数组会出现以下情况

在这里插入图片描述

源码:

Main->setAxisScale(QwtAxis::YLeft,0,1600,100);
Main->setAxisScale(QwtAxis::XBottom,0,200);double x[200];
double y[1600];
for(int x1 = 0; x1<200;x1++){x[x1] = x1;
}
for(int y1 = 0; y1<1600;y1++){y[y1] = y1;
}
sine_main[0].c->setSamples(x,y,1600);

若只修改上面的x[200]x[1600]之后都不修改

在这里插入图片描述

可看出,超出没赋值部分就是默认为0

只有这样写,我们才能的到直线

Main->setAxisScale(QwtAxis::YLeft,0,1600,100);
Main->setAxisScale(QwtAxis::XBottom,0,1600);double x[1600];
double y[1600];
for(int x1 = 0; x1<1600;x1++){
x[x1] = x1;
}
for(int y1 = 0; y1<1600;y1++){
y[y1] = y1;
}
sine_main[0].c->setSamples(x,y,1600);

在这里插入图片描述

可看出x轴一定要大于y轴,setSamples(x,y,显示大小)这个显示大小可以随x轴来获取

直方图
// 不设置这个属性,不会显示标签
//设置直方图
ui->qwtPlot->insertLegend(new QwtLegend()); //#include "qwt_legend.h"
ui->qwtPlot->setPalette(Qt::white);//设置背景
ui->qwtPlot->setAxisAutoScale(QwtAxis::XBottom,true);//自动设置轴
ui->qwtPlot->enableAxis(QwtAxis::XBottom,false);//取消方位坐标轴QwtPlotMultiBarChart *plotMultiBarChart = new QwtPlotMultiBarChart(); //#include "qwt_plot_multi_barchart.h"
plotMultiBarChart->setLayoutPolicy(QwtPlotMultiBarChart::AutoAdjustSamples);
plotMultiBarChart->setSpacing(20);
plotMultiBarChart->setMargin(3);static const char* colors[]={"DarkOrchid","SteelBlue","Gold"};//设置颜色数组
const int numSamples = 5; //设置通道
const int numBars = sizeof(colors)/sizeof(colors[0]);// 设置标签文字
QList<QwtText> titleList;
titleList.append(QwtText("001"));//标签文字名称
titleList.append(QwtText("002"));//标签文字名称
titleList.append(QwtText("003"));//标签文字名称
plotMultiBarChart->setBarTitles(titleList); //设置进
plotMultiBarChart->setLegendIconSize(QSize(10,10));//标签图标大小// 设置直方图属性
for(int i =0;i<numBars;i++){QwtColumnSymbol *symbol = new QwtColumnSymbol(QwtColumnSymbol::Box);symbol->setLineWidth(2);symbol->setFrameStyle(QwtColumnSymbol::NoFrame);symbol->setPalette(QPalette(colors[i]));plotMultiBarChart->setSymbol(i,symbol);
}
// 添加数据
QVector<QVector<double>> series;
for(int i=0;i<numSamples;i++){QVector<double> values;for(int j=0;j<numBars;j++){values+=(2+j%8); //这里进行大小的设置}series+=values;
}
// 显示到控件上
plotMultiBarChart->setSamples(series);
plotMultiBarChart->attach(ui->qwtPlot);

在这里插入图片描述

设置网格

QwtPlotGrid *gridTop = new QwtPlotGrid();
gridTop->setPen(Qt::gray, 0.0, Qt::DotLine);                //设置网格为灰色点线
gridTop->attach(ui->qwtPlot);

在这里插入图片描述

左键选中放大,右键恢复上级,CTRL+右键恢复原样

/* 默认左键选中放大,右键恢复上级,CTRL+右键恢复原样 */
//QwtPlotZoomer *zoomerTop;
zoomerTop = new MyZoomer(ui->qwtPlot->canvas());//plotTopLine->canvas()
zoomerTop->setMousePattern(QwtEventPattern::MouseSelect2, Qt::RightButton, Qt::ControlModifier);
zoomerTop->setMousePattern(QwtEventPattern::MouseSelect3, Qt::RightButton);

显示图标(一): QwtLegend

/*
Q_SIGNALS:void checked(const QVariant&,bool,int);
public slots:void legendChecked(const QVariant &, bool);
*/
QwtLegend *legend = new QwtLegend;
legend->setDefaultItemMode( QwtLegendData::Checkable );
ui->qwtPlot->insertLegend(legend,QwtPlot::RightLegend);
connect(legend,SIGNAL(checked(const QVariant&,bool,int)),SLOT(legendChecked( const QVariant &, bool )));/*
//图例选择事件
void ChanOne::legendChecked(const QVariant &itemInfo, bool on){//获取曲线QwtPlotItem *plotItem = ui->qwtPlot->infoToItem(itemInfo);if(plotItem){plotItem->setVisible(on);}ui->qwtPlot->replot();
}
*/

显示图标(二): QwtPlotLegendItem

  • 前提提示,需要一下操作才可以显示
QwtPlotCurve *a = new QwtPlotCurve(tr("A"));//设置曲线对象和图标文字
a->setPen(Qt::red,1);				//设置颜色
a->attach(ui->qwtPlot);             //将曲线添加到图表
//...

简单的显示

QwtPlotLegendItem *d_legendItemTop = new QwtPlotLegendItem();
d_legendItemTop->attach( ui->qwtPlot );

在这里插入图片描述

设置最大列数

QwtPlotLegendItem *d_legendItemTop = new QwtPlotLegendItem();
d_legendItemTop->setRenderHint( QwtPlotItem::RenderAntialiased );
d_legendItemTop->attach( ui->qwtPlot );
d_legendItemTop->setMaxColumns(1); //设置最大列数

在这里插入图片描述

对齐方式

//QwtPlotLegendItem *d_legendItemTop = new QwtPlotLegendItem();
//d_legendItemTop->setRenderHint( QwtPlotItem::RenderAntialiased );
//d_legendItemTop->attach( ui->qwtPlot );
//d_legendItemTop->setMaxColumns(1);                                          //设置最大列数
d_legendItemTop->setAlignmentInCanvas( Qt::AlignRight | Qt::AlignTop );     //对齐方式(右上)

在这里插入图片描述

设置背景颜色

//QwtPlotLegendItem *d_legendItemTop = new QwtPlotLegendItem();
//d_legendItemTop->setRenderHint( QwtPlotItem::RenderAntialiased );
//d_legendItemTop->attach( ui->qwtPlot );
//d_legendItemTop->setMaxColumns(1);                                          //设置最大列数
//d_legendItemTop->setAlignmentInCanvas( Qt::AlignRight | Qt::AlignTop );     //对齐方式(右上)
d_legendItemTop->setTextPen(QPen(QColor(Qt::white)));                       //设置字体颜色
d_legendItemTop->setBackgroundBrush(QColor(192, 192, 192, 192));            //设置背景颜色
d_legendItemTop->setBorderPen(QPen(QColor(Qt::blue)));                      //设置边框颜色

在这里插入图片描述

设置边框半径(圆弧)

//QwtPlotLegendItem *d_legendItemTop = new QwtPlotLegendItem();
//d_legendItemTop->setRenderHint( QwtPlotItem::RenderAntialiased );
//d_legendItemTop->attach( ui->qwtPlot );
//d_legendItemTop->setMaxColumns(1);                                          //设置最大列数
//d_legendItemTop->setAlignmentInCanvas( Qt::AlignRight | Qt::AlignTop );     //对齐方式(右上)
//d_legendItemTop->setTextPen(QPen(QColor(Qt::white)));                       //设置字体颜色
//d_legendItemTop->setBackgroundBrush(QColor(192, 192, 192, 192));            //设置背景颜色
//d_legendItemTop->setBorderPen(QPen(QColor(Qt::blue)));                      //设置边框颜色
d_legendItemTop->setBorderRadius(5);                                        //设置边框半径(圆弧)

在这里插入图片描述

设置边距

//QwtPlotLegendItem *d_legendItemTop = new QwtPlotLegendItem();
//d_legendItemTop->setRenderHint( QwtPlotItem::RenderAntialiased );
//d_legendItemTop->attach( ui->qwtPlot );
//d_legendItemTop->setMaxColumns(1);                                          //设置最大列数
//d_legendItemTop->setAlignmentInCanvas( Qt::AlignRight | Qt::AlignTop );     //对齐方式(右上)
//d_legendItemTop->setTextPen(QPen(QColor(Qt::white)));                       //设置字体颜色
//d_legendItemTop->setBackgroundBrush(QColor(192, 192, 192, 192));            //设置背景颜色
//d_legendItemTop->setBorderPen(QPen(QColor(Qt::blue)));                      //设置边框颜色
//d_legendItemTop->setBorderRadius(5);                                        //设置边框半径(圆弧)
d_legendItemTop->setMargin( 4 );                                            //设置内边距(x轴)

在这里插入图片描述

d_legendItemTop->setSpacing(4);                                             //设置内边距(y轴)

在这里插入图片描述

d_legendItemTop->setItemMargin(10);                                         //设置项目边距

在这里插入图片描述

QWT + FFT

字符串截取

我们不是将获取到的数据放入全局变量中了吗?那个是转换成16进制后转换成QString来进行显示的,所以我们需要数据处理的时候最简单的就是字符串的截取了

//mid
//QString strbuff = str.mid(索引值,截取大小)
QString pageHead = globalStr.mid(0,2);//0索引开始,取2位
QString initState = globalStr.mid(64,4);//64索引开始,取4位

进制转换

QString转int

//QString转int
QString hexstr = "e02";
bool ok;
int hexnum = hexstr.toInt(&ok,16); // 表示以16进制方式读取字符串
qDebug()<<hexnum<<endl;

注:ok表示转换是否成功,成功则ok为true,失败则ok为false。

QString转QByteArray(16进制)

page_set_Node.chan1_Array.append(strAllArray[i].toLatin1());

QByteArray(16进制)转float

float temp = (float)bytebuff.toFloat(&ok); //bool ok:返回值存放的变量,0为成功

字符串转float

float temp = (float)strbuff.toFloat(&ok); //bool ok:返回值存放的变量,0为成功

Qhostaddress 与 Qstring互转

QHostAddress ip;
QString strIp = ip.toString();
QString strIp;
QHostAddress ip = QHostAddress(strIp);

2个uint8_t拼接

uint8_t a = 0xAB;
uint8_t b = 0xCD;uint16_t result = ((uint16_t)a << 8) | b;printf("拼接结果为: %04X\n", result);

3个uint8_t拼接

我们将它转QStringarg()

#include <iostream>
#include <QString>
#include <QDebug>int main() {uint8_t value1 = 01;uint8_t value2 = 02;uint8_t value3 = 03;QString result = QString("%1%2%3").arg(value1).arg(value2).arg(value3);qDebug() << result.toStdString();//toStdString():转换成string类型return 0;
}

发现是123,但我们想要的先得到的是010203所以我们就要添加一些条件

#include <iostream>
#include <QString>
#include <QDebug>int main() {uint8_t value1 = 01;uint8_t value2 = 02;uint8_t value3 = 03;QString result = QString("%1%2%3").arg(value1,2,10,QChar('0')).arg(value2,2,10,QChar('0')).arg(value3,2,10,QChar('0'));qDebug() << result.toStdString();//toStdString():转换成string类型return 0;
}

可以的到010203但是若是091011的数据会呈现出091617,原因是他是到十进制是就加一。18进制10在十进制中就是16所以0x11就是17没问题。但是我们的数据毕竟是不是091011所以我们要看QString("%1").arg(value1,2,10,QChar('0'))这参数是什么定义

QString("%1").arg(,宽度,转换的进制,填充数)

所以可以这样来写

#include <iostream>
#include <QString>
#include <QDebug>int main() {uint8_t value1 = 09;uint8_t value2 = 10;uint8_t value3 = 11;QString result = QString("%1%2%3").arg(value1,2,16,QChar('0')).arg(value2,2,16,QChar('0')).arg(value3,2,16,QChar('0'));qDebug() << result.toStdString(); .//toStdString():转换成string类型return 0;
}

响应式控件改变位置

在这里插入图片描述

Qt:cannot open output file debug\XXX.exe: Permission denied

可能是软件未响应退出后,程序还运行着,之后你未关闭再次运行导致的错误

类型断言

静态类型断言

static_assert<数据类型>(实参)

reinterpret_cast

interpret解释,诠释,reinterpret重新诠释

相关文章:

QT学习之旅 - 一个QT的基本项目

文章目录 定时器(时间)位置信息QTableWidget用cellwidget添加控件隐藏QTableWidget的滚动条自动调整适应大小 UDPUDP ClientUDP ServerUDP udpSocket.readDatagram重要参数使用多线程udp 自定义信号和槽UDP服务端接收数据(全局变量) QWT设置标题数轴相关设置坐标轴范围设置坐标…...

大数据课程D2——hadoop的概述

文章作者邮箱&#xff1a;yugongshiyesina.cn 地址&#xff1a;广东惠州 ▲ 本章节目的 ⚪ 了解hadoop的定义和特点&#xff1b; ⚪ 掌握hadoop的基础结构&#xff1b; ⚪ 掌握hadoop的常见命令&#xff1b; ⚪ 了解hadoop的执行流程&#xff1b; 一、简介 1…...

使用nginx和ffmpeg搭建HTTP FLV流媒体服务器(摄像头RTSP视频流->RTMP->http-flv)

名词解释 RTSP &#xff08;Real-Time Streaming Protocol&#xff09; 是一种网络协议&#xff0c;用于控制实时流媒体的传输。它是一种应用层协议&#xff0c;通常用于在客户端和流媒体服务器之间建立和控制媒体流的传输。RTSP允许客户端向服务器发送请求&#xff0c;如…...

揭秘APT团体常用的秘密武器——AsyncRAT

AsyncRAT 是 2019 年 1 月在 [GitHub](https://github.com/NYAN-x-CAT/AsyncRAT-C- Sharp)上开源的远控木马&#xff0c;旨在通过远程加密链接控制失陷主机&#xff0c;提供如下典型功能&#xff1a; 截取屏幕 键盘记录 上传/下载/执行文件 持久化 禁用 Windows Defender 关机/…...

Flutter Widget Life Cycle 组件生命周期

Flutter Widget Life Cycle 组件生命周期 视频 前言 了解 widget 生命周期&#xff0c;对我们开发组件还是很重要的。 今天会把无状态、有状态组件的几个生命周期函数一起过下。 原文 https://ducafecat.com/blog/flutter-widget-life-cycle 参考 https://api.flutter.dev/f…...

LeetCode面向运气之Javascript—第2600题-K件物品的最大和-94.68%

LeetCode第2600题-K件物品的最大和 题目要求 袋子中装有一些物品&#xff0c;每个物品上都标记着数字 1 、0 或 -1 。 四个非负整数 numOnes 、numZeros 、numNegOnes 和 k 。 袋子最初包含&#xff1a; numOnes 件标记为 1 的物品。numZeroes 件标记为 0 的物品。numNegOn…...

数学建模学习(4):TOPSIS 综合评价模型及编程实战

一、数据总览 需求&#xff1a;我们需要对各个银行进行评价&#xff0c;A-G为银行的各个指标&#xff0c;下面是银行的数据&#xff1a; 二、代码逐行实现 清空代码和变量的指令 clear;clc; 层次分析法 每一行代表一个对象的指标评分 p [8,7,6,8;7,8,8,7];%每一行代表一个…...

PHP之Smarty使用以及框架display和assign原理

一、Smarty的下载 进入Smarty官网下载&#xff0c;复制目录libs目录即可http://www.smarty.net/http://www.smarty.net/ 二、使用Smarty&#xff0c;创建目录demo,把libs放进去改名为Smarty 三、引入Smarty配置,创建目录&#xff0c;index.php文件配置 <?php…...

《TCP IP网络编程》第十一章

第 11 章 进程间通信 11.1 进程间通信的基本概念 通过管道实现进程间通信&#xff1a; 进程间通信&#xff0c;意味着两个不同的进程中可以交换数据。下图是基于管道&#xff08;PIPE&#xff09;的进程间通信的模型&#xff1a; 可以看出&#xff0c;为了完成进程间通信&…...

Folx Pro 5 最好用的Mac磁力链接BT种子下载工具

除了迅雷&#xff0c;还有哪个支持磁力链接下载&#xff1f;Mac电脑如何下载磁力链接&#xff1f;经常有小伙伴问老宅。今天&#xff0c;老宅给大家推荐Folx Pro For Mac&#xff0c;Mac系统超好用的磁力下载工具。 Folx是一款功能强大且易于使用的Mac下载管理器&#xff0c;并…...

Redis 数据库的高可用

文章目录 Redis 数据库的高可用一.Redis 数据库的持久化1.Redis 高可用概念2.Redis 实现高可用的技术2.1 持久化2.2 主从复制2.3 哨兵2.4 Cluster集群 3.Redis 持久化3.1 持久化的功能3.2 Redis 提供持久化的方式3.2.1 RDB 持久化3.2.2 AOF 持久化&#xff08;append only file…...

elementPlus dialog组件设置可拖动,当内容高度大于视口高度拖动显示异常的解决办法

elementPlus UI的dialog弹框组件在设置了draggable属性后就可拖动弹框&#xff0c;但是当弹框的内容高度大于视口高度时去拖动弹框就会出现显示问题。 解决办法&#xff08;修改源码&#xff09; 去node_modules下面找到element-plus文件夹&#xff0c;按照以下路径修改onMou…...

亲测解决Git inflate: data stream error (incorrect data check)

Git inflate: data stream error (incorrect data check) error: unable to unpack… 前提是你的repository在github等服务器或者其他路径有过历史备份/副本&#xff0c;不要求是最新版本的&#xff0c;只要有就可能恢复你做的所有工作。 执行git fsck --full检查损坏的文件 在…...

Ansible 自动化运维工具

Ansible 简介 Ansible 自动化运维工具&#xff08;机器管理工具&#xff09;可以实现批量管理多台&#xff08;成百上千&#xff09;主机&#xff0c;应用级别的跨主机编排工具。现在也在自动化管理领域大放异彩。它融合了众多老牌运维工具的优点&#xff0c;Pubbet和Saltstac…...

node.js 爬虫图片下载

主程序文件 app.js 运行主程序前需要先安装使用到的模块&#xff1a; npm install superagent --save axios要安装指定版,安装最新版会报错&#xff1a;npm install axios0.19.2 --save const {default: axios} require(axios); const fs require(fs); const superagent r…...

VAE-根据李宏毅视频总结的最通俗理解

1.VAE的直观理解 先简单了解一下自编码器&#xff0c;也就是常说的Auto-Encoder。Auto-Encoder包括一个编码器&#xff08;Encoder&#xff09;和一个解码器&#xff08;Decoder&#xff09;。其结构如下&#xff1a; 自编码器是一种先把输入数据压缩为某种编码, 后仅通过该编…...

【LangChain】检索器之上下文压缩

LangChain学习文档 【LangChain】检索器(Retrievers)【LangChain】检索器之MultiQueryRetriever【LangChain】检索器之上下文压缩 上下文压缩 LangChain学习文档 概要内容使用普通向量存储检索器使用 LLMChainExtractor 添加上下文压缩(Adding contextual compression with an…...

uniapp 语音文本播报功能

最近uniapp项目上遇到一个需求 就是在接口调用成功的时候加上语音播报 &#xff0c; ‘创建成功’ ‘开始成功’ ‘结束成功’ 之类的。 因为是固定的文本 &#xff0c;所以我先利用工具生成了 文本语音mp3文件&#xff0c;放入项目中&#xff0c;直接用就好了。 这里用到的工…...

腾讯云高IO型云服务器CPU型号处理器主频性能

腾讯云服务器高IO型CVM实例CPU处理器主频性能说明&#xff0c;高IO型云服务器具有高随机IOPS、高吞吐量、低访问延时等特点&#xff0c;适合对硬盘读写和时延要求高的高性能数据库等I/O密集型应用&#xff0c;腾讯云服务器网分享高IO型云服务器IT5和IT3的CPU处理器说明&#xf…...

【数据结构】实验八:树

实验八 树 一、实验目的与要求 1&#xff09;理解树的定义&#xff1b; 2&#xff09;掌握树的存储方式及基于存储结构的基本操作实现&#xff1b; 二、 实验内容 题目一&#xff1a;采用树的双亲表示法根据输入实现以下树的存储&#xff0c;并实现输入给定结点的双亲结点…...

day52 ResNet18 CBAM

在深度学习的旅程中&#xff0c;我们不断探索如何提升模型的性能。今天&#xff0c;我将分享我在 ResNet18 模型中插入 CBAM&#xff08;Convolutional Block Attention Module&#xff09;模块&#xff0c;并采用分阶段微调策略的实践过程。通过这个过程&#xff0c;我不仅提升…...

【论文笔记】若干矿井粉尘检测算法概述

总的来说&#xff0c;传统机器学习、传统机器学习与深度学习的结合、LSTM等算法所需要的数据集来源于矿井传感器测量的粉尘浓度&#xff0c;通过建立回归模型来预测未来矿井的粉尘浓度。传统机器学习算法性能易受数据中极端值的影响。YOLO等计算机视觉算法所需要的数据集来源于…...

【2025年】解决Burpsuite抓不到https包的问题

环境&#xff1a;windows11 burpsuite:2025.5 在抓取https网站时&#xff0c;burpsuite抓取不到https数据包&#xff0c;只显示&#xff1a; 解决该问题只需如下三个步骤&#xff1a; 1、浏览器中访问 http://burp 2、下载 CA certificate 证书 3、在设置--隐私与安全--…...

论文浅尝 | 基于判别指令微调生成式大语言模型的知识图谱补全方法(ISWC2024)

笔记整理&#xff1a;刘治强&#xff0c;浙江大学硕士生&#xff0c;研究方向为知识图谱表示学习&#xff0c;大语言模型 论文链接&#xff1a;http://arxiv.org/abs/2407.16127 发表会议&#xff1a;ISWC 2024 1. 动机 传统的知识图谱补全&#xff08;KGC&#xff09;模型通过…...

什么是EULA和DPA

文章目录 EULA&#xff08;End User License Agreement&#xff09;DPA&#xff08;Data Protection Agreement&#xff09;一、定义与背景二、核心内容三、法律效力与责任四、实际应用与意义 EULA&#xff08;End User License Agreement&#xff09; 定义&#xff1a; EULA即…...

Rust 异步编程

Rust 异步编程 引言 Rust 是一种系统编程语言,以其高性能、安全性以及零成本抽象而著称。在多核处理器成为主流的今天,异步编程成为了一种提高应用性能、优化资源利用的有效手段。本文将深入探讨 Rust 异步编程的核心概念、常用库以及最佳实践。 异步编程基础 什么是异步…...

【OSG学习笔记】Day 16: 骨骼动画与蒙皮(osgAnimation)

骨骼动画基础 骨骼动画是 3D 计算机图形中常用的技术&#xff0c;它通过以下两个主要组件实现角色动画。 骨骼系统 (Skeleton)&#xff1a;由层级结构的骨头组成&#xff0c;类似于人体骨骼蒙皮 (Mesh Skinning)&#xff1a;将模型网格顶点绑定到骨骼上&#xff0c;使骨骼移动…...

听写流程自动化实践,轻量级教育辅助

随着智能教育工具的发展&#xff0c;越来越多的传统学习方式正在被数字化、自动化所优化。听写作为语文、英语等学科中重要的基础训练形式&#xff0c;也迎来了更高效的解决方案。 这是一款轻量但功能强大的听写辅助工具。它是基于本地词库与可选在线语音引擎构建&#xff0c;…...

【VLNs篇】07:NavRL—在动态环境中学习安全飞行

项目内容论文标题NavRL: 在动态环境中学习安全飞行 (NavRL: Learning Safe Flight in Dynamic Environments)核心问题解决无人机在包含静态和动态障碍物的复杂环境中进行安全、高效自主导航的挑战&#xff0c;克服传统方法和现有强化学习方法的局限性。核心算法基于近端策略优化…...

Java编程之桥接模式

定义 桥接模式&#xff08;Bridge Pattern&#xff09;属于结构型设计模式&#xff0c;它的核心意图是将抽象部分与实现部分分离&#xff0c;使它们可以独立地变化。这种模式通过组合关系来替代继承关系&#xff0c;从而降低了抽象和实现这两个可变维度之间的耦合度。 用例子…...