# Qt开发的通用函数库 **Repository Path**: Mike_Zhou_Admin/Mike_Zhou_MY_QT_DEF ## Basic Information - **Project Name**: Qt开发的通用函数库 - **Description**: 为了使开发更方便 对使用到的模块进行了总结 最终封装成了一个类、函数库 使用typedef、class类、回调函数等来建立 方便打包和开发 文章: https://blog.csdn.net/weixin_53403301/article/details/141467062 - **Primary Language**: C++ - **License**: AGPL-3.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 2 - **Forks**: 0 - **Created**: 2024-08-23 - **Last Updated**: 2025-12-04 ## Categories & Tags **Categories**: Uncategorized **Tags**: Qt, 嵌入式, 上位机 ## README # 【Qt开发】建立自己的Qt基本类、函数库封装 包括图表、多线程、串口等 #### 介绍 为了使开发更方便 对使用到的模块进行了总结 最终封装成了一个类、函数库 使用typedef、class类、回调函数等来建立 方便打包和开发 文章: https://blog.csdn.net/weixin_53403301/article/details/141467062 后续更新以gitee为准 更新了移植LVGL的API函数库 https://blog.csdn.net/weixin_53403301/article/details/144278246 【Qt移植LVGL】QWidget手搓LVGL模拟软件仿真模拟器(非直接运行图形库) # QtCharts绘图 [【Qt开发】QtCharts图表 在ui上添加QChartView控件并进行绘图配置](https://mikezhou.blog.csdn.net/article/details/141168015) 可以实现一键配置 ```cpp #ifndef MY_QT_DEF_H #define MY_QT_DEF_H #include #include #include #include #include #include QT_CHARTS_USE_NAMESPACE typedef struct { float min; float max; QString tittle; QString format; Qt::Alignment alignment; QValueAxis *axis; }MY_QChartView_Float_Axis_Struct; //splineSeries曲线实例化(折线用QLineSeries) typedef struct { int maxSize; QList data; QString tittle; MY_QChartView_Float_Axis_Struct X; MY_QChartView_Float_Axis_Struct Y; QPainter::RenderHint renderHint; //上面是必配置的参数 下面是指针类型 QSplineSeries *splineSeries; QChart *chart; QChartView *chartView; }MY_QChartView_Float_Struct; void Init_MY_QChartView_Float_Axis_Struct(MY_QChartView_Float_Axis_Struct *Stu,QChart *chart); void Init_MY_QChartView_Float_Struct(MY_QChartView_Float_Struct *Stu); void Add_MY_QChartView_Float_Value(MY_QChartView_Float_Struct *Stu,float value); #endif // MY_QT_DEF_H ``` ```cpp #include "MY_QT_DEF.h" void Init_MY_QChartView_Float_Axis_Struct(MY_QChartView_Float_Axis_Struct *Stu,QChart *chart) { Stu->axis->setLabelFormat(Stu->format); Stu->axis->setTitleText(Stu->tittle); chart->addAxis(Stu->axis, Stu->alignment); Stu->axis->setRange(Stu->min,Stu->max); } void Init_MY_QChartView_Float_Struct(MY_QChartView_Float_Struct *Stu) { Stu->chart=new QChart(); Stu->splineSeries = new QSplineSeries(); Stu->X.axis=new QValueAxis(); Stu->Y.axis=new QValueAxis(); Stu->chart->legend()->hide(); Stu->chart->setTitle(Stu->tittle); Stu->chart->addSeries(Stu->splineSeries); Init_MY_QChartView_Float_Axis_Struct(&Stu->X,Stu->chart); Init_MY_QChartView_Float_Axis_Struct(&Stu->Y,Stu->chart); Stu->splineSeries->attachAxis(Stu->X.axis); Stu->splineSeries->attachAxis(Stu->Y.axis); Stu->chartView->setChart(Stu->chart); Stu->chartView->setRenderHint(Stu->renderHint); } //添加数据自动移动函数 void Add_MY_QChartView_Float_Value(MY_QChartView_Float_Struct *Stu,float value) { Stu->data.append(value); while (Stu->data.size() > Stu->maxSize) { Stu->data.removeFirst(); } Stu->splineSeries->clear(); float xSpace = (Stu->X.max-Stu->X.min) / (Stu->maxSize - 1); for (int i = 0; i < Stu->data.size(); ++i) { Stu->splineSeries->append(xSpace * i, Stu->data.at(i)); } } ``` # 继承QObject的QThread多线程 采用moveToThread方法执行多线程 对整体进行了封装 可以自我调用 可以通过注册回调函数来进行不同的工作 [【Qt开发】多线程QThread(通过QObject::moveToThread)和QMutex互斥锁的配置和多线程类的封装及回调函数](https://mikezhou.blog.csdn.net/article/details/141252352) ```cpp //QObject的多线程示例 class MY_Thread_Worker; class MY_Thread_Worker : public QObject { Q_OBJECT private: QMutex lock; bool isCanRun; bool isCanStart; MY_QT_CALLBACK pfCallback; public slots: void Judg_doWork(void) { this->isCanRun=true; //执行 while(this->isCanRun) { QMutexLocker locker(&this->lock); pfCallback(this,0,NULL); } isCanStart=true; } signals: void startWork(void); public: void * pArg; QThread *workerThread; void stopWork(bool Wait_Flag) { this->isCanRun = false; if(Wait_Flag) { QMutexLocker locker(&this->lock); } } bool startThread(void) { if(!isCanRun && isCanStart) { isCanStart=false; workerThread->start(); emit this->startWork(); return true; } return false; } bool stopThread(bool Wait_Flag) { if(workerThread->isRunning()) { stopWork(Wait_Flag); return true; } return false; } void closeThread(void) { stopThread(false); this->workerThread->quit(); } MY_Thread_Worker(MY_QT_CALLBACK const pfunc,QThread * worker_Thread = nullptr) { pfCallback=pfunc; pArg=nullptr; if(!worker_Thread) { this->workerThread = new QThread; } else { this->workerThread = worker_Thread; } this->moveToThread(workerThread); this->stopWork(false); isCanStart=true; connect(workerThread, SIGNAL(finished()),this, SLOT(deleteLater())); connect(workerThread, SIGNAL(finished()), workerThread, SLOT(deleteLater())); connect(this, SIGNAL(startWork()), this, SLOT(Judg_doWork())); // connect(this, SIGNAL(startWork(QString)), worker, SLOT(Judg_doWork(QString))); 主窗口发送函数 // connect(worker, SIGNAL(resultReady(QString)),this, SLOT(handleResults(QString))); 主窗口接收函数 } ~MY_Thread_Worker() { closeThread(); } }; ``` # QSerialPort串口配置、发送、接收回调函数 包装的类具有 单线程/多线程 回调函数/虚函数四种配置方案 同样采用回调函数方便配置和修改 [【Qt开发】QSerialPort串口配置、发送、接收回调函数 多线程接收的串口类封装](https://mikezhou.blog.csdn.net/article/details/141365298) ```cpp class MY_SerialPort_Thread; class MY_SerialPort_Thread : public QObject { Q_OBJECT private: QMutex lock; bool isCanRun; bool isCanStart; bool Thread_Flag; MY_QT_CALLBACK pfCallback; public slots: void SerialPort_RX(void) { SerialPort_RX_Ready_Callback(this); } void Callback_SerialPort_RX(void) { pfCallback(this,0,NULL); } void RX_Thread(void) { this->isCanRun=true; //执行 while(isCanRun) { QMutexLocker locker(&this->lock); if(SerialPort.waitForReadyRead(1)) { SerialPort_RX_Thread_Callback(this); } } isCanStart=true; } void Callback_RX_Thread(void) { this->isCanRun=true; //执行 while(isCanRun) { QMutexLocker locker(&this->lock); if(SerialPort.waitForReadyRead(1)) { pfCallback(this,1,NULL); } } isCanStart=true; } signals: void Start_RX_Thread(void); public: QSerialPort SerialPort; QList SerialPort_List; QString SerialPort_Name; uint32_t BaudRate; uint8_t DataBits; uint8_t StopBits; QSerialPort::Parity Parity; QSerialPort::FlowControl FlowControl; bool Open_Flag; uint8_t RX_Data; uint8_t *RX_Buf; uint32_t RX_Buf_Size; uint32_t RX_Flag; QThread workerThread; void Stop_Port(uint8_t TX_RX_All) { switch(TX_RX_All) { case 0:SerialPort.clear(QSerialPort::Output);break; case 1:SerialPort.clear(QSerialPort::Input);break; default:SerialPort.clear();SerialPort.flush();break; } } void Scan_SerialPort(void) { SerialPort_List.clear(); foreach (const QSerialPortInfo &info,QSerialPortInfo::availablePorts()) { SerialPort_List.append(info.portName()); } } void Clean_RX(void) { RX_Flag=0; RX_Data=0; memset(RX_Buf,0,RX_Buf_Size); } void Reset_SerialPort(void) { Scan_SerialPort(); BaudRate=115200; DataBits=8; StopBits=1; Parity=QSerialPort::NoParity; FlowControl = QSerialPort::NoFlowControl; if(Open_Flag) { Stop_Port(2); } Clean_RX(); } bool Ctrl_SerialPort(bool OpenNotClose) { if(OpenNotClose) { SerialPort.setPortName(SerialPort_Name); SerialPort.setBaudRate(BaudRate); SerialPort.setFlowControl(FlowControl); switch(DataBits) { case 5:SerialPort.setDataBits(QSerialPort::Data5);break; case 6:SerialPort.setDataBits(QSerialPort::Data6);break; case 7:SerialPort.setDataBits(QSerialPort::Data7);break; case 8:SerialPort.setDataBits(QSerialPort::Data8);break; default:break; } SerialPort.setParity(Parity); switch(StopBits) { case 1:SerialPort.setStopBits(QSerialPort::OneStop);break; case 2:SerialPort.setStopBits(QSerialPort::TwoStop);break; case 3:SerialPort.setStopBits(QSerialPort::OneAndHalfStop);break; default:break; } if (!SerialPort.open(QIODevice::ReadWrite)) { return false; } Open_Flag=true; if(this->Thread_Flag) { startThread(); } return true; } stopThread(true); Open_Flag=false; SerialPort.close(); return true; } uint32_t SerialPort_TX_Sequence(uint8_t *buf,uint32_t size) { if(Open_Flag) { return SerialPort.write((char *)buf,size); } return 0; } uint32_t SerialPort_TX(uint8_t *buf,uint32_t size) { if(Open_Flag) { SerialPort.clear(QSerialPort::Output); return SerialPort.write((char *)buf,size); } return 0; } virtual void SerialPort_RX_Ready_Callback(MY_SerialPort_Thread *port) { Q_UNUSED(port); foreach (const uint8_t i,port->SerialPort.readAll()) { port->RX_Data=i; SerialPort_RX_Callback(port); } } virtual void SerialPort_RX_Thread_Callback(MY_SerialPort_Thread *port) { Q_UNUSED(port); foreach (const uint8_t i,port->SerialPort.readAll()) { port->RX_Data=i; SerialPort_RX_Callback(port); } } virtual void SerialPort_RX_Callback(MY_SerialPort_Thread *port) { Q_UNUSED(port); qDebug()<RX_Data; } void stopWork(bool Wait_Flag) { this->isCanRun = false; if(Wait_Flag) { QMutexLocker locker(&this->lock); } } bool startThread(void) { if(!isCanRun && isCanStart) { isCanStart=false; workerThread.start(); emit this->Start_RX_Thread(); return true; } return false; } bool stopThread(bool Wait_Flag) { if(workerThread.isRunning()) { stopWork(Wait_Flag); return true; } return false; } void closeThread(void) { stopThread(false); this->workerThread.quit(); } MY_SerialPort_Thread(uint32_t Buf_Size=256,bool ThreadNotNormal=false,MY_QT_CALLBACK const pfunc=nullptr) { pfCallback=pfunc; SerialPort_Name=""; Open_Flag=false; RX_Buf_Size = Buf_Size; RX_Buf = new uint8_t[RX_Buf_Size]; SerialPort.setReadBufferSize(RX_Buf_Size); this->Thread_Flag = ThreadNotNormal; Reset_SerialPort(); if(Thread_Flag) { this->moveToThread(&workerThread); this->stopWork(false); isCanStart=true; connect(&workerThread, SIGNAL(finished()),this, SLOT(deleteLater())); connect(&workerThread, SIGNAL(finished()), &workerThread, SLOT(deleteLater())); if(pfCallback) { connect(this, SIGNAL(Start_RX_Thread()), this, SLOT(Callback_RX_Thread())); } else { connect(this, SIGNAL(Start_RX_Thread()), this, SLOT(RX_Thread())); } } else { if(pfCallback) { connect(&this->SerialPort, SIGNAL(readyRead()),this, SLOT(Callback_SerialPort_RX())); } else { connect(&this->SerialPort, SIGNAL(readyRead()),this, SLOT(SerialPort_RX())); } } } ~MY_SerialPort_Thread() { Open_Flag=false; SerialPort.close(); delete RX_Buf; closeThread(); } }; ```