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

news2024/11/19 5:57:25

文章目录

      • 定时器(时间)
      • 位置信息
      • 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");//对位服务器IP
        quint16 _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);

    //udp
    udpServer = 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重新诠释

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/799524.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

赌博应用引风波,苹果、Meta、谷歌官司缠身,被视为“博彩公司”

一名美国法官认定&#xff0c;苹果、Meta、谷歌等科技巨头允许在其应用商店上架赌博应用程序的行为可能涉及从赌博活动中获利&#xff0c;类似于博彩公司。然而&#xff0c;该判决存在模糊的界限&#xff0c;并且法官认为这些公司有权提出上诉。 “苹果公司被指控在其应用商店上…

win11安装appium

node安装 node下载网址: Download | Node.js 安装后对node安装包路径进行配置 npm config set prefix “E:\nodejs\node_global” //设置全局包目录 npm config set cache “E:\nodejs\node_cache” //设置缓存目录npm config list //查看npm配置npm install -g appium //安…

Java 网络编程基础

文章目录 前言什么是网络编程网络编程基础知识网络通讯流程长连接和短连接Socket Java 网络编程总结 前言 一个网络请求、服务之间的调用都需要进行网络通讯&#xff0c;在日常开发时我们可能并不会关心我们的服务端是怎么接收到请求的、调用别的服务是怎么调用的&#xff0c;…

HCIP——OSPF不规则区域划分及LSA详解

ZY技术分享 一、OSPF与RIP异同二、OSPF的不规则区域划分1、远离骨干的非骨干使用tunnel隧道使用虚链路使用多进程双向重发布 2、不连续骨干 三、OSPF的LSA详解LSA头部Type - 1LSAType - 2LSAType - 3LSAType - 5LSAType - 4LSA 一、OSPF与RIP异同 OSPFRIP v1RIP v2链路状态路由…

行星碰撞(力扣)栈 JAVA

给定一个整数数组 asteroids&#xff0c;表示在同一行的行星。 对于数组中的每一个元素&#xff0c;其绝对值表示行星的大小&#xff0c;正负表示行星的移动方向&#xff08;正表示向右移动&#xff0c;负表示向左移动&#xff09;。每一颗行星以相同的速度移动。 找出碰撞后剩…

Mysql的增删改查

一.增加数据&#xff08;insert&#xff09; insert into 表名&#xff08;列名1&#xff0c;列名2&#xff0c;列名3&#xff0c;.....列名n&#xff09;values(值&#xff0c;值&#xff0c;值&#xff0c;....值&#xff09; insert into userinfo(id,name,age) values(&quo…

每日一题——除自身以外数组的乘积

除自身以外数组的乘积 题目链接 这一题乍一看好像十分简单&#xff0c;先用一趟循环遍历所有数据&#xff0c;得到数据所有元素的乘积&#xff0c;再用一趟循环将这个乘积除以每个元素&#xff0c;这样不就得到了除自身以外数组的乘积吗&#xff1f;我们先来看看代码&#xff…

janus-Gateway的服务端部署

janus-Gateway 需求是前后端的webRTC推拉流&#xff0c;但是后端用的是c&#xff0c;于是使用了这个库做视频流的推送和拉取&#xff0c;记录踩坑过程。 如果你也需要自己部署janus的服务端并在前端拉流测试&#xff0c;希望对你有所帮助。 由于janus的服务器搭建需要linux环境…

Python——Windows下载ffmpeg

目录 前言 一、下载 &#xff08;3种下载方式&#xff09; 1、第一种下载方式——我上传的文件 2、第二种下载方式——GitHub下载 3、第三种下载方式——官网下载 二、解压 三、配置环境变量 四、验证是否安装成功 五、其他 关于ffmpeg其他安装教程 ffmpeg的延迟问题 …

重生之再学mysql-数据库三范式

数据库三范式 介绍第一范式&#xff1a;确保每列都是不可拆分的第二范式&#xff1a;在第一范式的基础上&#xff0c;确保非主键列完全依赖于主键&#xff0c;而不是依赖于主键的一部分第三范式&#xff1a;第二范式的基础上&#xff0c;确保非主键列不存在传递依赖 介绍 什么…

“可以黑掉整个宇宙”的Metasploit Framework

0x01、 简述 Metasploit Framework(MSF)是一款开源安全漏洞检测工具&#xff0c;他带有数千个已知的软件漏洞&#xff0c;目前人在持续更新。Metasploit可以用来信息收集、漏洞探测、漏洞利用等渗透测试的全流程&#xff0c;被安全社区冠以“可以黑掉整个宇宙”之名。在普通的…

Nginx最佳实践优化(动静分离、资源压缩、负载均衡、黑白名单等等)

一、前言 Nginx是目前负载均衡技术中的主流方案&#xff0c;几乎绝大部分项目都会使用它&#xff0c;Nginx是一个轻量级的高性能HTTP反向代理服务器&#xff0c;同时它也是一个通用类型的代理服务器&#xff0c;支持绝大部分协议&#xff0c;如TCP、UDP、SMTP、HTTPS等。 二、…

4.3. 重载和重写的区别

重载就是同样的一个方法能够根据输入数据的不同&#xff0c;做出不同的处理 重写就是当子类继承自父类的相同方法&#xff0c;输入数据一样&#xff0c;但要做出有别于父类的响应时&#xff0c;你就要覆盖父类方法 重载&#xff1a; 发生在同一个类中&#xff08;或者父类和子…

Python入门【函数用法和底层分析、函数简介 、函数的定义和调用、形参和实参、文档字符串(函数的注释) 、函数也是对象,内存底层分析】(十)

&#x1f44f;作者简介&#xff1a;大家好&#xff0c;我是爱敲代码的小王&#xff0c;CSDN博客博主,Python小白 &#x1f4d5;系列专栏&#xff1a;python入门到实战、Python爬虫开发、Python办公自动化、Python数据分析、Python前后端开发 &#x1f4e7;如果文章知识点有错误…

一文让你知道等保测评以及渗透测试的区别与联系

我国等保政策已经严格落地执行&#xff0c;不少企业准备办理过等保。但大家对于等保相关政策不是很了解&#xff0c;例如傻傻分不清楚等保测评和渗透测试&#xff0c;这里一文让你知道等保测评以及渗透测试的区别与联系&#xff0c;仅供参考哦&#xff01; 等保测评以及渗透测试…

SpringBoot 项目使用 Redis 对用户 IP 进行接口限流

一、思路 使用接口限流的主要目的在于提高系统的稳定性&#xff0c;防止接口被恶意打击&#xff08;短时间内大量请求&#xff09;。 比如要求某接口在1分钟内请求次数不超过1000次&#xff0c;那么应该如何设计代码呢&#xff1f; 下面讲两种思路&#xff0c;如果想看代码可…

记一次Apache HTTP Client问题排查

现象 通过日志查看&#xff0c;存在两种异常情况。第一种&#xff1a;开始的时候HTTP请求会报超时异常。 762663363 [2023-07-21 06:04:25] [executor-64] ERROR - com.xxl.CucmTool - CucmTool|sendRisPortSoap error,url:https://xxxxxx/realtimeservice/services/RisPort o…

【NodeJs】如何将Markdown文件生成HTML文件在线浏览

经常用的编辑器是Markdown&#xff0c;有自带预览排版效果功能的&#xff0c;预览的是HTML网页&#xff0c;如果想要将它转换成HTML网页文件&#xff0c;要怎么做呢。 首先&#xff0c;借助Node的插件来做&#xff0c;在使用前&#xff0c;确保电脑已安装了NodeJS应用&#xf…

git本地库和远程库的相关操作命令

目录 一、分支概念&#xff1a; 二、 本地库分支管理&#xff1a; 1. 查看分支情况&#xff1a; 命令1&#xff1a;git branch 2. 新建分支 命令1&#xff1a; git branch <分支名> 命令2&#xff1a; git branch <新建分支名> <源分支名> 命令3&…

【温故而知新】【中间件】Redis为什么这么快?

时间&#xff1a;2023年07月27日 作者&#xff1a;小蒋聊技术 邮箱&#xff1a;wei_wei10163.com 微信&#xff1a;wei_wei10 【温故而知新】【中间件】Redis为什么这么快&#xff1f;_小蒋聊技术_免费在线阅读收听下载 - 喜马拉雅欢迎收听小蒋聊技术的类最新章节声音“【温…