基于Qt的上位机通用框架
0.前言
最近一年多的时间一直在开发设备控制相关的软件,加上之前在聚光的两年时间,前前后后开发这种设备控制类型的上位机软件也有三年的时间了。总结出了一套基于Qt的上位机编程框架,核心思想类似于C#的依赖注入,对象的初始化都是基于反射和配置文件生成的,通过修改配置文件就能实现控制流程的修改。
该框架分为基本模块、通讯层、设备层、指令层、控制层五个核心模块,上层调用下层,主要通过Manager单例读取配置json文件,创建并配置对应实体,再将实体指针由Manager管理,可以有效防止内存泄漏等问题。
项目gitee地址
1.基本模块
定义了BaseFactory、BaseItem、BaseManager三个底层基类,BaseFactory定义了类型注册和实体创建两个方法,主要用于每个模块内的实体创建工作。
#pragma execution_character_set("utf-8")
#ifndef BASEFACTORY_H
#define BASEFACTORY_H
#include <QObject>
#include <QMap>
#include <QDebug>
#include "BaseItem.h"
class BaseFactory
{
public:
BaseFactory();
virtual BaseItem* CreateInstance(QString concreteType);
template <typename T1>
int Register()
{
int preCount=_map.count();
const QMetaObject& meta = T1::staticMetaObject;
_map.insert(meta.className(),&meta);
if(preCount+1!=_map.count())
{
throw QString("%1注册失败,请检查!").arg(meta.className());
}
return _map.count();
}
protected:
QMap<QString,const QMetaObject*> _map;
};
BaseItem主要定义了框架内所有实体的配置接口和配置文件创建接口
#pragma execution_character_set("utf-8")
#ifndef BASEITEM_H
#define BASEITEM_H
#include <QObject>
#include <QJsonObject>
#include <QJsonDocument>
#include <QException>
#include <QSharedPointer>
#include <QDebug>
#include "InterruptedException.h"
class BaseItem : public QObject
{
Q_OBJECT
public:
explicit BaseItem(QObject *parent = nullptr);
QString Name();
void SetName(QString name);
virtual void SetConfig(QJsonObject obj);
virtual QJsonObject Config();
virtual void SetOtherConfig(QJsonObject other);
virtual bool Init();
virtual QWidget* GetConfigWidget();
virtual QSharedPointer<QWidget> GetConfigWidgetZZZ();
protected:
QString _name;
QJsonObject _obj;
QJsonObject _other;
signals:
public slots:
};
#endif // BASEITEM_H
BaseManager主要定义了Manager类的的基本方法,主要通过读取配置文件,使用工厂模式创建对应的实体对象,再将配置文件中的json对象参数传入对象完成初始化,最后再将这些实体对象指针通放入QList容器,简化对象的管理和监控。
2.通讯层
定义了SendReply、Publisher、Subscriber、Requester、Replyer、Modbus物种基本的通讯类。并且实现了SendReply、Modbus通讯方式的网口和串口模式,基于zmq实现了Publisher、Subscriber、Requester、Replyer四种通讯模式。
CommunicationManger创建并且管理这些通讯实例,并且具有通讯监控、断线重连等功能,方便再设备运行期间对通讯状态的异常排查。
3.设备层
定义了IO模块、测距仪、电机控制器等常用设备,完成了不同品牌的具体实现
4.指令层/控制层
整体业务核心部分,将所有软件执行流程分为分解为多个指令,内部通告异常抛出实现控制流程的中断,大大简化控制流程,通过调整不同指令的位置,可以实现控制流程的自由组合。通过设置不同的权重,可以实现进度报告等功能。
5.中断
将整体业务执行流程分为瞬态控制和等待,在每个等待中使用WaitMs(int time)
方法实现业务的中断功能。
#pragma execution_character_set("utf-8")
#include "WaitUtils.h"
#include <QTime>
#include <QDebug>
#include <QCoreApplication>
#include <QElapsedTimer>
WaitUtils::WaitUtils(QObject *parent) : QObject(parent)
{
}
bool WaitUtils::_isRunning=false;
void WaitUtils::WaitMs(int time)
{
//多处调用displayProgress该变量且有的时true有的时false时会导致进度显示异常,想不通。。。
QElapsedTimer ela;
ela.start();
while (ela.elapsed() < time)
{
CheckIsRunning();
QCoreApplication::processEvents(QEventLoop::AllEvents, 100);
}
}
void WaitUtils::WaitMsNoException(int msec)
{
//多处调用displayProgress该变量且有的时true有的时false时会导致进度显示异常,想不通。。。
QElapsedTimer ela;
ela.start();
while (ela.elapsed() < msec)
{
QCoreApplication::processEvents(QEventLoop::AllEvents, 300);
}
}
void WaitUtils::Reset()
{
_isRunning=true;
}
void WaitUtils::Stop()
{
_isRunning=false;
}
void WaitUtils::WaitMsNoProgress(int time)
{
QElapsedTimer ela;
ela.start();
while (ela.elapsed() < time)
{
CheckIsRunning();
QCoreApplication::processEvents(QEventLoop::AllEvents, 300);
}
}
void WaitUtils::CheckIsRunning()
{
if(!_isRunning)
{
throw QString("流程中止");
}
}
7.设计模式
本框架主要使用指令模式、工厂模式、模板模式这三种设计模式,感兴趣的读者可以去看看gof的《设计模式》。
原文地址:https://blog.csdn.net/weixin_43988887/article/details/140598906
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!