【C++ QT项目实战-03】---- C++ QT系统实现读取JSON文件数据的自动化模式

🎩 欢迎来到技术探索的奇幻世界👨‍💻

📜 个人主页@一伦明悦-CSDN博客

✍🏻 作者简介C++软件开发、Python机器学习爱好者

🗣️ 互动与支持💬评论      👍🏻点赞      📂收藏     👀关注+

如果文章有所帮助,欢迎留下您宝贵的评论!

欢迎点赞加收藏支持我,点击关注,一起进步!


前言      

        本篇在该篇博客的基础上,继续进行系统功能的完善操作,比如,一般生产国臣各种,跟定希望机器是能自动化的,这样即使工作人员不在,生产依然在进行。

【C++ QT项目实战-02】---- C++ QT系统实现基于QT调用RESTful接口访问JSON文件中数据-CSDN博客文章浏览阅读457次,点赞5次,收藏3次。本篇在做项目的基础上进行了项目中难点的一些总结,我们都知道,在如今大数据时代下,数据对项目系统开发起到决定性的作用,可以帮助企业实现实时决策、提升用户体验、实现业务智能、提高系统性能、提供定制化服务和增强业务竞争力等方面的优势,有利于项目系统的发展和成功。因此,在项目系统开发过程中,需要充分重视数据的快速读取和处理能力,以满足日益增长的数据需求和用户期望。https://blog.csdn.net/m0_59951855/article/details/139065776

        项目中的计算等功能已经是自动化模式的,这里的难题就是如何在读取数据的过程中也实现自动化模式,当然,为了便于操作,不仅需要自动化模式,也需要随时可以切换到手动模式。

        这里包含了以下几个难点:

        (1)主系统线程与计算线程是双线程运行,两种模式下,如何进行线程通信?

        (2)自动模式下,系统访问平台的方式,或者说是否需要给定时间,定时访问平台?而不是不停歇的访问。

        (3)自动模式下如何实现系统读完数据直接进行计算,手动模式下又怎样切换?这些也需要进行解决。

        (4)如何判断平台中是否存在数据,当判断之后,又该怎样运行?
        带着这四个问题,将进行详细分析如何实现这些功能,并给出代码解释和功能演示。

正文 

01- 双模式下,主线程与计算线程通信实现   

        主界面上的自动和手动两种模式通过控件进行选择,当选择自动模式时,主线程发送一个信号,通过信号与槽函数的方式与计算线程中的函数进行连接。

        在自动模式下,发送信号 send_cmBox_ToWFC,计算线程中使用函数cmBox_switch()和model_switch()来接收信号并实现各种功能。在手动模式下,发送信号 send_modelcmBox_ToWFC,计算线程中使用函数model_switch_0来接收信号。

这种设计模式可以让你在不同模式下灵活地控制计算线程的行为,实现自动化或手动化操作。

mainwindow.h文件

#ifndef MAINWINDOW_H
#define MAINWINDOW_H
/*#include "Mp_Pred.h"*/
#include"ui_mainwindow.h"
#include <QMainWindow>
#include <QLabel>

#include "spdlog/fmt/ostr.h"
#include "Zanj_WFC_ctrl.h"
#include <QVariant>
#include "wfc_to_main.h"

#include <QtSql/QtSql>
#include <QDateTime>
#include <QTimer>
#include <qtextcodec.h> 
#include <QtWidgets/QApplication>
#include <QtWidgets/QMainWindow>
#include <QtCharts/QChartView>
#include <QtCharts/QBarSeries>
#include <QtCharts/QBarSet>
#include <QtCharts/QLegend>
#include <QtCharts/QBarCategoryAxis>
#include <QMouseEvent>
//一定要声明!!!
#include"dialog_data_log.h"

namespace Ui {
	class MainWindow;
}

};
class MainWindow : public QMainWindow
{
	Q_OBJECT

public:
	explicit MainWindow(QWidget *parent = nullptr);
	~MainWindow();

	Zanj_WFC_ctrl * m_Zanj_WFC_ctrl; // 预报计算的类
	QThread * m_Zanj_WFC_ctrl_Thread; //m_Mp_Pred将被移动到此线程执行
	void connectZanj_WFC_ctrl(Zanj_WFC_ctrl *m_Zanj_WFC_ctrl);


signals:

	void send_cmBox_ToWFC();
	void send_modelcmBox_ToWFC();




mainwindow.cpp文件


#include  <QTimer>
#include  <time.h>
#include  <QLabel>
#include  <QValueAxis>
#include  <QMargins>
#include  <QtWidgets/QApplication>
#include  <QtWidgets/QMainWindow>
#include  <QtCharts/QChartView>
#include  <QtCharts/QBarSeries>
#include  <QtCharts/QBarSet>
#include  <QtCharts/QLegend>
#include  <QtCharts/QBarCategoryAxis>
#include <ctime>  

using namespace std::literals;
// using namespace fmt;
using namespace std;
namespace spd = spdlog;
auto console_mainWindow = spd::stdout_color_mt("主界面控制台");
auto rotating_logger_mainWindow = spdlog::rotating_logger_mt("baori_CAO8_Winmain_rotating", "logs/baori_CAO8_rotating.logger", 1048576 * 5, 12);

MainWindow::MainWindow(QWidget *parent) :
	QMainWindow(parent),
	ui(new Ui::MainWindow)
{
	ui->setupUi(this);



	OpenDatabase();
	//Matlab_mcl_Init();

	setWindowTitle(QString::fromLocal8Bit("主系统")); // 此处写应用程序在标题栏上显示的名称
	
	setStyleSheet("background - color:pink; ");
	reshow();
	data_log_tblview();

	
	connect(this, &MainWindow::send_cmBox_ToWFC, m_Zanj_WFC_ctrl, &Zanj_WFC_ctrl::cmBox_switch);
	connect(this, &MainWindow::send_cmBox_ToWFC, m_Zanj_WFC_ctrl, &Zanj_WFC_ctrl::model_switch);
	connect(this, &MainWindow::send_modelcmBox_ToWFC, m_Zanj_WFC_ctrl, &Zanj_WFC_ctrl::model_switch_0);
}

MainWindow::~MainWindow()
{
	delete ui;
}


void MainWindow::deploy_cmBox_switch()
{
	if (ui->deploy_cmBox->currentText() == QString::fromLocal8Bit("自动模式"))
	{
		ui->Iplate4j_IP_QLE->setText("127.0.0.1");
		ui->model_PC_IP_QLE->setText("127.0.0.1");
		emit send_cmBox_ToWFC();
	}

	else if (ui->deploy_cmBox->currentText() == QString::fromLocal8Bit("手动模式"))
	{
		emit send_modelcmBox_ToWFC();
	}
}

02-cmBox_switch()函数实现  

        这里接受信号的计算线程的函数分为两个,第一个cmBox_switch()函数是实现打开配置文件和定时访问数据,定时访问数据这里加入死循环,设置30s的时间间隔。

        startSystem()函数的这段代码是一个无限循环,在每次循环中执行以下操作:

         调用 OnGETSlot() 函数:这个函数用于执行数据读取和预测的操作。具体实现可能涉及从网络或文件系统中读取数据,并对数据进行处理和预测。

         调用 this_thread::sleep_for(chrono::seconds(30)):这行代码会使当前线程暂停执行,模拟定时器或轮询间隔。在这个例子中,线程会休眠30秒钟,然后再次执行循环中的操作。        

        整体来说,这段代码实现了一个简单的定时器功能,每隔30秒钟执行一次数据读取和预测的操作,然后再次休眠30秒钟,循环执行这个过程        


计算线程.cpp文件


void Zanj_WFC_ctrl::cmBox_switch()
{
	
	configuration_read();
	startSystem();	
}


bool Zanj_WFC_ctrl::configuration_read()
{
	string err;
	QFile config_ini("config.ini");
	//QFile config_ini("config_baori.ini");  打开baori配置文件,如果需要访问宝日大数据平台,就需要打开baori配置文件
	if (!config_ini.open(QIODevice::ReadOnly | QIODevice::Text))
	{
		console_WFC_thread->critical("配置文件config.ini不能打开!");
		rlogger_WFC_thread->critical("配置文件config.ini不能打开!");
		//		std::cout << "configuration.ini Open failed." << endl;
		return false;
	}
	console_WFC_thread->info("配置文件config.ini已打开! ");
	rlogger_WFC_thread->info("配置文件config.ini已打开! ");

	QTextStream config_txtInput(&config_ini);
	QString config_lineStr;

	config_lineStr = config_txtInput.readLine();

	config_lineStr = config_txtInput.readLine();
	clientID = config_lineStr.mid(9);
	config_lineStr = config_txtInput.readLine();
	clientSecret = config_lineStr.mid(13);
	config_lineStr = config_txtInput.readLine();
	serverIP = config_lineStr.mid(9);
	config_lineStr = config_txtInput.readLine();
	serviceID_get = config_lineStr.mid(14);
	config_lineStr = config_txtInput.readLine();
	serviceID_post = config_lineStr.mid(15);

	config_lineStr = config_txtInput.readLine();
	name = config_lineStr.mid(5);

	config_lineStr = config_txtInput.readLine();
	unit = config_lineStr.mid(5);


	config_lineStr = config_txtInput.readLine();
	user_ID = config_lineStr.mid(8);
	config_lineStr = config_txtInput.readLine();
	companyCode = config_lineStr.mid(12);


	config_lineStr = config_txtInput.readLine();
	mssql_serverName = config_lineStr.mid(17);

	config_lineStr = config_txtInput.readLine();
	mssql_dbName = config_lineStr.mid(13);
	config_lineStr = config_txtInput.readLine();
	mssql_username = config_lineStr.mid(15);
	config_lineStr = config_txtInput.readLine();
	mssql_pwd = config_lineStr.mid(10);
	config_lineStr = config_txtInput.readLine();
	mssql_datasource = config_lineStr.mid(17);

	return true;
}



void Zanj_WFC_ctrl::startSystem() {
	while (true) {
		// 每隔一定时间执行一次数据读取和预测
		OnGETSlot();
		//Temp_KNNval_Auto_Cal();
		// 休眠一段时间,模拟定时器或轮询间隔
		this_thread::sleep_for(chrono::seconds(30)); // 30秒钟间隔
	}
}

03-model_switch()函数实现  

       实现另一个函数之前,先定义了一个全局变量,用于设置工作模式,这里设置的是,当变量为0,为手动模式,变量为1,为自动模式,在读取数据函数那里,加入if判断语句,如果变量为1,则直接进行计算,否则,需要手动计算

        如果变量为1,直接调用该函数Temp_KNNval_Auto_Cal()进行计算,如果为0,则手动操作进行计算。

计算线程.cpp文件



void Zanj_WFC_ctrl::json_doc_get_parse()
{

	//总的思路是:对象.value(),如果取到string、int、double类型 就直接.toString()等输出;
	//如果取到object或array类型 ,就通过toObject()或toArray() 转到对象或数组类型,接着取值。。循环
	if (json_doc_get.isNull())
	{
		console_WFC_thread->critical("unable to parse! ");
		rlogger_WFC_thread->critical("unable to parse! ");
	}

	else
	{
		console_WFC_thread->info("parse start! ");
		rlogger_WFC_thread->info("parse start! ");
	}

	QJsonObject::Iterator it;
	for (it = doc_get_Obj.begin(); it != doc_get_Obj.end(); ++it) 
	{
		HdglPredict tempData;
		QString aentid, atentid, atime, acode, agrade, asource;
		float ahthick, athick, awidth, CT_TMP, FT_TMP, DSH, SPEED, TPM;
		float C, Si, Mn, P, S, Cu, Ni, Cr, Mo, Nb, Ti, B, N, Al;
		int st_product_no;
		QString zoneKey = it.key();
		QJsonObject zoneObj = it.value().toObject();

		// 检查钢卷是否已经读取过,如果已经读取过,则跳过
		if (readCoils.contains(zoneKey))
		{
			
			console_WFC_thread->warn("文件里没有其他钢卷! ");
			continue;
		}

		// 将已读取的钢卷添加到集合中
		readCoils.insert(zoneKey);

		aentid = zoneObj["aentid"].toString();
		atentid = zoneObj["atentid"].toString();
		atime = zoneObj["atime"].toString();
		acode = zoneObj["acode"].toString();
		agrade = zoneObj["agrade"].toString();
		asource = zoneObj["asource"].toString();


		tempData.ZoneKey = zoneKey;
		tempData.ENTID = aentid;
		tempData.AENTID = atentid;
		tempData.ATIME = atime;
		tempData.ST_code = acode;
		tempData.ST_grade = agrade;
		tempData.ST_source = asource;
		tempData.CGL_SPEED_INPUT = SPEED;
		tempData.SPM_ELONG_INPUT = TPM;

		tempData.st_product_no = st_product_no_determin();
		// 将结构体对象添加到容器中
		hdglPredictList.append(tempData);

		
		
		
		strt_hdgl_predict.ENTID = aentid;
		strt_hdgl_predict.AENTID = atentid;
		strt_hdgl_predict.ATIME = atime;
		strt_hdgl_predict.ST_code = acode;
		strt_hdgl_predict.ST_grade = agrade;
		strt_hdgl_predict.ST_source = asource;
		strt_hdgl_predict.CGL_SPEED_INPUT = SPEED;
		strt_hdgl_predict.SPM_ELONG_INPUT = TPM;

	

		if (model_switch_num == 1)
		{
			Temp_KNNval_Auto_Cal();
		} 
		else
		{
			continue;
		}
		
		
	}


}





void Zanj_WFC_ctrl::model_switch() {

	model_switch_num = 1;

}
void Zanj_WFC_ctrl::model_switch_0() {

	model_switch_num = 0;

}

04-数据存在判断操作实现  

       最后实现系统对平台是否存在新的数据的判断,定义了一个字符串变量readCoils,用于存储已经读取的钢卷,对于已经读取过的钢卷,直接跳过,不进行计算,若是没有钢卷存在,系统也会发出警告。通过下面这部分代码判断即可

        if (readCoils.contains(zoneKey))
        {
            
            console_WFC_thread->warn("文件里没有其他钢卷! ");
            continue;
        }

        // 将已读取的钢卷添加到集合中
        readCoils.insert(zoneKey);

void Zanj_WFC_ctrl::json_doc_get_parse()
{

	//总的思路是:对象.value(),如果取到string、int、double类型 就直接.toString()等输出;
	//如果取到object或array类型 ,就通过toObject()或toArray() 转到对象或数组类型,接着取值。。循环
	if (json_doc_get.isNull())
	{
		console_WFC_thread->critical("unable to parse! ");
		rlogger_WFC_thread->critical("unable to parse! ");
	}

	else
	{
		console_WFC_thread->info("parse start! ");
		rlogger_WFC_thread->info("parse start! ");
	}

	QJsonObject::Iterator it;
	for (it = doc_get_Obj.begin(); it != doc_get_Obj.end(); ++it) 
	{
		HdglPredict tempData;
		QString aentid, atentid, atime, acode, agrade, asource;
		float ahthick, athick, awidth, CT_TMP, FT_TMP, DSH, SPEED, TPM;
		float C, Si, Mn, P, S, Cu, Ni, Cr, Mo, Nb, Ti, B, N, Al;
		int st_product_no;
		QString zoneKey = it.key();
		QJsonObject zoneObj = it.value().toObject();

		// 检查钢卷是否已经读取过,如果已经读取过,则跳过
		if (readCoils.contains(zoneKey))
		{
			
			console_WFC_thread->warn("文件里没有其他钢卷! ");
			continue;
		}

		// 将已读取的钢卷添加到集合中
		readCoils.insert(zoneKey);

		aentid = zoneObj["aentid"].toString();
		atentid = zoneObj["atentid"].toString();
		atime = zoneObj["atime"].toString();
		acode = zoneObj["acode"].toString();
		agrade = zoneObj["agrade"].toString();
		asource = zoneObj["asource"].toString();


		tempData.ZoneKey = zoneKey;
		tempData.ENTID = aentid;
		tempData.AENTID = atentid;
		tempData.ATIME = atime;
		tempData.ST_code = acode;
		tempData.ST_grade = agrade;
		tempData.ST_source = asource;
		tempData.CGL_SPEED_INPUT = SPEED;
		tempData.SPM_ELONG_INPUT = TPM;

		tempData.st_product_no = st_product_no_determin();
		// 将结构体对象添加到容器中
		hdglPredictList.append(tempData);

		
		
		
		strt_hdgl_predict.ENTID = aentid;
		strt_hdgl_predict.AENTID = atentid;
		strt_hdgl_predict.ATIME = atime;
		strt_hdgl_predict.ST_code = acode;
		strt_hdgl_predict.ST_grade = agrade;
		strt_hdgl_predict.ST_source = asource;
		strt_hdgl_predict.CGL_SPEED_INPUT = SPEED;
		strt_hdgl_predict.SPM_ELONG_INPUT = TPM;

	

		if (model_switch_num == 1)
		{
			Temp_KNNval_Auto_Cal();
		} 
		else
		{
			continue;
		}
		
		
	}


}

  05-功能演示  

      下面对上述介绍的功能进行演示:

   如下图所示,为系统登录界面,登录之后,才可以对各种功能进行操作。 

         主界面如下图所示:仅展示部分主界面,分为自动模式和手动模式

        选择自动模式之后,就可以持续进行计算,不断进行访问数据文件 

         当再次访问,发现数据文件中没有数据之后,便会发出警告,如下图所示。

 总结      

       在C++ QT系统中实现自动化读取JSON数据文件的过程有几个好处:

        提高效率:自动化读取JSON数据文件可以省去手动操作的时间和精力,提高系统运行效率。特别是在需要定期更新或获取数据时,自动化读取可以保证数据及时可用,减少了人为干预的需要。

        减少错误:手动处理JSON数据文件容易出现错误,例如文件路径错误、解析错误等。自动化读取通过编程实现,可以减少人为错误的发生,提高系统的稳定性和可靠性。

        增强灵活性:自动化读取JSON数据文件的实现可以根据需求进行定制化,例如可以设置读取频率、读取条件等,从而增强了系统的灵活性和可配置性。

        方便维护:通过自动化读取,可以将数据获取的逻辑封装在函数或模块中,便于维护和修改。当需求变化时,只需要修改相应的代码逻辑,而不必修改大量的手动操作步骤。

        综上所述,自动化读取JSON数据文件可以提高系统效率、减少错误、增强灵活性,并方便系统的维护和升级。

  • 32
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 11
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一伦明悦

感谢,您的支持是我最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值