应用场景与问题描述

问题是这样的,我写了很多命令行程序用于处理遥感影像,这种方式很方便,可以通过dos或shell脚本来实现批处理。但这也引起一个问题,当我在集成时偷懒,不想做界面,而用户又必须要求有个界面时,我不得不做一个窗口来体现我是有界面的,于是我决定直接调用我的可执行程序或者批处理脚本,但这些命令和脚本不能在终端或dos窗口里执行。这个问题简单的抽象为执行一个"ping localhost"的命令,并且把输出重定向到我的消息窗口里。

我们习惯于先看看别人有没有做过这个事,于是先百度一下,就直接看到这篇博客: 点击打开链接 ,参照这个博客的例子,我做了如下的实验:

#ifndef QTWINMSG_H
#define QTWINMSG_H
#include <QtWidgets/QMainWindow>
#include "ui_qtwinmsg.h"
#include "Worker.h"
class QtWinMsg : public QMainWindow
	Q_OBJECT
public:
	QtWinMsg(QWidget *parent = 0);
	~QtWinMsg();
public slots:
	void onTest();
private:
	Ui::QtWinMsgClass ui;
#endif // QTWINMSG_H
#include "qtwinmsg.h"
#include <QMessageBox>
#include <conio.h>  
#include <stdio.h>  
#include <windows.h> 
QtWinMsg::QtWinMsg(QWidget *parent)
	: QMainWindow(parent)
	ui.setupUi(this);
	ui.lineEdit->setText(tr("ping localhost"));
	ui.textEdit->setLineWrapMode(QTextEdit::NoWrap);
	connect(ui.pushButton,SIGNAL(clicked()),this,SLOT(onTest()));
QtWinMsg::~QtWinMsg()
void QtWinMsg::onTest()
	QString qsCmd =  ui.lineEdit->text();
	QByteArray qbCmd = qsCmd.toLocal8Bit();
	char* pszCmd = qbCmd.data();
	LPWSTR ppCmd = new TCHAR[100];
	LPSTR p = pszCmd;
	MultiByteToWideChar(CP_ACP, 0, p, -1, ppCmd, 100);
	SECURITY_ATTRIBUTES   sa;   
	HANDLE   hRead,hWrite;   
	sa.nLength   =   sizeof(SECURITY_ATTRIBUTES);   
	sa.lpSecurityDescriptor   =   NULL;   
	sa.bInheritHandle   =   TRUE;   
	if   (!CreatePipe(&hRead,&hWrite,&sa,0))     
		return  ;   
	STARTUPINFO   si;   
	PROCESS_INFORMATION   pi;     
	si.cb   =   sizeof(STARTUPINFO);   
	GetStartupInfo(&si);     
	si.hStdError   =   hWrite;   
	si.hStdOutput   =   hWrite;   
	si.wShowWindow   =   SW_HIDE;   
	si.dwFlags   =   STARTF_USESHOWWINDOW   |   STARTF_USESTDHANDLES;   
	//关键步骤,CreateProcess函数参数意义请查阅MSDN   
	if   (!CreateProcess(NULL,   ppCmd   
		,NULL,NULL,TRUE,NULL,NULL,NULL,&si,&pi))     
		return  ;   
	CloseHandle(hWrite);   
	char   buffer[4096]   =   {0};   
	DWORD   bytesRead;     
	//ofstream outfile("log.txt");  
	while   (true)     
		if   (ReadFile(hRead,buffer,4095,&bytesRead,NULL)   ==   NULL)   
			break;   
		//buffer中就是执行的结果,可以保存到文本,也可以直接输出   
		//printf(buffer);   
		//outfile << buffer << endl;  
		//Sleep(1000);   
		QString qsMsg = QString::fromLocal8Bit(buffer);
		ui.textEdit->append(qsMsg);
		this->update();
	//outfile.close(); 

运行效果:

这样可以实现目标,但是在Qt程序里使用了Win32 API,这是有点别扭,另外输出的消息并不是动态的输出,而是在执行完毕后一下子刷出来,即使我们通过QThread,把处理过程放到其它线程里,然后通过异步的事件来刷新消息输出也是实现不了动态消息效果。总体来说,这种方式是不完美的。

我想Qt应该有自己的方式。通过查看Qt的帮助,很快就可以找到做这个事情的类QProcess,QProcess可以同于执行外部程序和命令,并且支持消息重定向和标准输入、输出,有了QProcess类,前面讲到的问题就可以简单的通过下面的方式来实现了:

#ifndef TEST2_H
#define TEST2_H
#include <QWidget>
#include <QProcess>
#include "ui_Test2.h"
class Test2 : public QWidget
	Q_OBJECT
public:
	Test2(QWidget *parent = 0);
	~Test2();
	public slots:
		void onTest();
		void onOutput();
private:
	Ui::Test2 ui;
	QProcess  *m_Process;
#endif // TEST2_H
#include "Test2.h"
#include <QTextEdit>
Test2::Test2(QWidget *parent)
	: QWidget(parent),m_Process(new QProcess)
	ui.setupUi(this);
	ui.lineEdit->setText(tr("ping localhost"));
	ui.textEdit->setLineWrapMode(QTextEdit::NoWrap);
	m_Process->setProcessChannelMode(QProcess::MergedChannels);
	connect(ui.pushButton,SIGNAL(clicked()),this,SLOT(onTest()));
	connect(m_Process,SIGNAL(readyReadStandardOutput()),this,SLOT(onOutput()));
Test2::~Test2()
	m_Process->terminate();
void Test2::onTest()
	QString qsCmd = ui.lineEdit->text();
	m_Process->start( qsCmd);
void Test2::onOutput()
	QByteArray qbt = m_Process->readAllStandardOutput();
	QString msg = QString::fromLocal8Bit(qbt);
	ui.textEdit->append(msg);
	ui.textEdit->update();

运行效果:

应用场景与问题描述:问题是这样的,我写了很多命令行程序用于处理遥感影像,这种方式很方便,可以通过dos或shell脚本来实现批处理。但这也引起一个问题,当我在集成时偷懒,不想做界面,而用户又必须要求有个界面时,我不得不做一个窗口来体现我是有界面的,于是我决定直接调用我的可执行程序或者批处理脚本,但这些命令和脚本不能在终端或dos窗口里执行。这个问题简单的抽象为执行一个&quot;ping localhost...
获取文件单行内容类似于获取一个数组中的某个元素内容,把需要调用的数据、指令写入一个文件中可以减轻代码量,也方便外人管理。话不多说,主要代码如下:首先创建一个.txt文件,并输入你要调用的内容然后创建qt项目,ui界面设置如下: 在.h中添加相应头文件 在.cpp中 最终运行结果如下:...
目录一、项目介绍二、项目基本配置三、UI界面设计四、主程序实现4.1 widget.h头文件4.2 widget.cpp源文件五、效果演示 一、项目介绍 利用QProcess类实现启动进程的功能进阶(以dos命令dir为例)。 二、项目基本配置 新建一个Qt案例,项目名称为“ProcessTest”,基类选择“QWidget”,点击选中创建UI界面复选框,完成项目创建。 三、UI界面设计 UI界面布局如下: 界面中只创建了1个控件,其名称和类型如下: HEADERS #头文件 FORMS #用到的ui文件(ui文件时用QT设计器生成的) INCLUDEPATH #这个用来指定头文件路径, 例如:INCLUDEPATH += ./mitab LIBS #加载动态库。例如:LIBS += ./mitab/libmita
在.pro 文件中添加 Config += console,qt 中将显示控制台窗口,并会将qDebug()中的信息输入到控制台中 等价于 在 项目配置中 ,qmake 额外参数项中加入 "CONFIG+=console",或者如下 qt .pro 工程文件中输出日志 使用message 函数message("ArcGIS Runtime...
Qt执行Linux命令可以使用QProcess类。该类允许您启动外部程序并与其进行交互。您可以使用QProcess类来执行Linux命令并获取输出。以下是一个示例: QProcess process; process.start("ls", QStringList() << "-l" << "/home"); process.waitForFinished(); QString output = process.readAllStandardOutput(); qDebug() << output; 在此示例中,我们使用QProcess类启动了一个名为“ls”的外部程序,并向其传递了两个参数:“-l”和“/home”。然后,我们等待该进程完成,并使用readAllStandardOutput()函数获取输出。最后,我们将输出打印到控制台。 请注意,使用QProcess类执行Linux命令可能会导致安全问题。因此,您应该仅在信任的环境中使用它。