qt 调用cmd 并输入到界面

场景

Win10 QT5.9
使用QProcess调用cmd,利用qt自带的槽函数把原本打印到cmd的信息,打印到界面

界面

在这里插入图片描述
保存按钮 ui.pushButton:点击运行cmd,所以需要一个槽函数Slot_Test()

connect(ui.pushButton, SIGNAL(clicked()), this, SLOT(Slot_Test()));

运行cmd是借助qt自带的QProcess (在头文件中定义 成员变量 m_Process)

QProcess 自带的信号:

  1. 读就绪-readyRead()
  2. 标准读就绪-readyReadStandardOutput()
  3. 产生错误-errorOccurred()
  4. 进程完成-finished()
    编写对应的槽函数即可输出到 界面 ui.textBrowser->append(msg);
    在这里插入图片描述
    参考文献:https://blog.csdn.net/Hxj_CSDN/article/details/89066330?spm=1001.2014.3001.5506

代码

logs.h

#pragma once
#include <QDialog>
#include "ui_logs.h"
#include <QProcess>
class logs:public QDialog
{
	Q_OBJECT
public:
	logs(QWidget *parent = Q_NULLPTR);
	~logs();
private slots:
	void Slot_errorProcess();
	void Slot_finishedProcess(int exitCode);
	void Slot_value_changed(int nValue);
	void Slot_Test();
private:
	Ui::logs ui;
	QProcess  m_Process;

logs.cpp

首先是槽函数

logs::logs(QWidget *parent)
	: QDialog(parent)
{
	ui.setupUi(this);
	init();
	connect(ui.pushButton, SIGNAL(clicked()), this, SLOT(Slot_Test()));//cmd
	connect(&m_Process, SIGNAL(readyRead()), this, SLOT(Slot_readData()));//读就绪
	connect(&m_Process, SIGNAL(readyReadStandardOutput()), this, SLOT(Slot_readData()));//标准读就绪
	connect(&m_Process, SIGNAL(errorOccurred()), this, SLOT(Slot_errorProcess()));//产生错误
	connect(&m_Process, SIGNAL(finished(int, QProcess::ExitStatus)), this, SLOT(Slot_finishedProcess(int, QProcess::ExitStatus)));//进程完成
}

启动cmd 使用start

void logs::Slot_Test()
{  
	QString strBasePath = QApplication::applicationDirPath() + "\\" + POSITIVESAMPLE_PATH;
	QString pythonCommand = QString("python main_test.py --pretrained_path %1 ").arg(m_strPretrainedModelPath);
	QString strBat = QString("positiveSampleTool.bat");
	QFile file;
	file.setFileName(strBasePath + strBat);
	if (file.open(QIODevice::WriteOnly))
	{
		file.write("@echo off\r\n");
		file.write("cd ..\ \r\n");
		file.write("cd bin/train/PaddleX_Train \r\n"); 
		file.write("call activate\r\n");
		file.write(pythonCommand.toLocal8Bit());
		file.write("\r\n");
		file.write("exit");
		file.close();
	}
	else
	{
		return;
	}
	
	m_Process.start(strBasePath+"\\positiveSample\\positiveSampleTool.bat");
}

打印到界面


void logs::Slot_readData()
{
	QByteArray qbt = m_Process.readAllStandardOutput();
	QString msg = QString::fromLocal8Bit(qbt);
	ui.textBrowser->append(msg);
}

void logs::Slot_errorProcess()
{
	QString msg = m_Process.errorString();
	ui.textBrowser->append("<font color=\"#FF0000\">" + msg +  + "</font>");
}
void logs::Slot_finishedProcess(int exitCode)
{
	ui.textBrowser->append("finished");
	ui.textBrowser->append("end");
	InitDatas();
}

我的QProcess 写为成员变量 m_Process;
在类的构造函数中 编写信号槽

logs::logs(QWidget *parent)
	: QDialog(parent)
{
	ui.setupUi(this);
	init();
	connect(ui.pushButton, SIGNAL(clicked()), this, SLOT(Slot_Test()));//cmd
	connect(&m_Process, SIGNAL(readyRead()), this, SLOT(Slot_readData()));//读就绪
	connect(&m_Process, SIGNAL(readyReadStandardOutput()), this, SLOT(Slot_readData()));//标准读就绪
	connect(&m_Process, SIGNAL(errorOccurred()), this, SLOT(Slot_errorProcess()));//产生错误
	connect(&m_Process, SIGNAL(finished(int, QProcess::ExitStatus)), this, SLOT(Slot_finishedProcess(int, QProcess::ExitStatus)));//进程完成
}

然后就坑了,信号槽只有第一次好使,再启动进程就不行了
于是添加以下代码:

if (m_Process.atEnd())
{
runTestFile();
disconnect(&m_Process, SIGNAL(readyRead()), this, SLOT(Slot_readData()));//读就绪
disconnect(&m_Process, SIGNAL(readyReadStandardOutput()), this, SLOT(Slot_readData()));//标准读就绪
disconnect(&m_Process, SIGNAL(errorOccurred()), this, SLOT(Slot_errorProcess()));//产生错误
disconnect(&m_Process, SIGNAL(finished(int, QProcess::ExitStatus)), this, SLOT(Slot_finishedProcess(int, QProcess::ExitStatus)));//进程完成
connect(&m_Process, SIGNAL(readyRead()), this, SLOT(Slot_readData()));//读就绪
connect(&m_Process, SIGNAL(readyReadStandardOutput()), this, SLOT(Slot_readData()));//标准读就绪
connect(&m_Process, SIGNAL(errorOccurred()), this, SLOT(Slot_errorProcess()));//产生错误
connect(&m_Process, SIGNAL(finished(int, QProcess::ExitStatus)), this, SLOT(Slot_finishedProcess(int, QProcess::ExitStatus)));//进程完成
}

如果是在类的构造函数中,定义QProcess 的信号槽。那么QProcess 第二次启动时,信号槽就失效了。
因为QProcess 的主体变了。‘所以每次有新的进程需要启动,都需要手动disconnect和connect一次
保存QProcess 每次都正确连上了信号槽

坑二:

disconnect(&m_Process, SIGNAL(readyReadStandardError()), this, SLOT(Slot_readErrorData()));//错误就绪
connect(&m_Process, SIGNAL(readyReadStandardError()), this, SLOT(Slot_readErrorData()));//错误就绪


void xx::Slot_readErrorData()
{
	QByteArray qbt = m_Process.readAllStandardError();
	QString msg = QString::fromLocal8Bit(qbt);
	ui.textBrowser->append(msg);
}

如果不加readyReadStandardError 相关操作,下面的信息就收不到:

Traceback (most recent call last):
  File "./semi/tools/train_ad.py", line 99, in <module>

AttributeError: module 'jcutils.base' has no attribute 'savepath'

坑三 实时显示

QT QProcess 使用及实时输出回显
网上都说 加 fflush(stdout)
但是我不管用,后来在被调用的pytho程序里
每一行print 后面后刷新一遍缓存,QProcess 就能实时显示了

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值