QT通过QProcess执行终端命令并实时输出回显

Published on with 5 views and 0 comments

在 QT 程序中我们经常需要与其他的程序间进行交互,而与终端进行交互就是一个例子。在不需要获取返回信息的情况下我们可以直接使用”system()”函数执行,但是当需要获取执行的结果或者需要实时地将结果输出到窗口上时,就比较难办了,需要涉及进程管道等等。而 QT 提供的 QProcess 类则大大简化了这一过程。

QProcess 是 QT 提供的与外部程序进行交互的一个类,主要使用到以下的函数:

start();     //启动一个进程
kill();         //关闭启动的外部进程
write();     //向外部进程写入数据
readAllStandardOutput();     //读取外部进程的标准输出
readAllStandardError();        //读取外部进程的错误信息
  • 创建 QProcess 对象并连接信号与槽
cmd = new QProcess(this);
connect(cmd , SIGNAL(readyReadStandardOutput()) , this , SLOT(on_readoutput()));
connect(cmd , SIGNAL(readyReadStandardError()) , this , SLOT(on_readerror()));
  • 实现槽函数

接收到标准输出:

void MainWindow::on_readoutput()
{
    ui->textEdit->append(cmd->readAllStandardOutput().data());   //将输出信息读取到编辑框
}

接收到错误信息:

void MainWindow::on_readerror()
{
    QMessageBox::information(0, "Error", cmd->readAllStandardError().data());    //弹出信息框提示错误信息
}
  • 启动外部程序并写入数据
cmd->start("bash");             //启动终端(Windows下改为cmd)
cmd->waitForStarted();        //等待启动完成
cmd->write("ls\n");               //向终端写入“ls”命令,注意尾部的“\n”不可省略

没有意外的话在编辑框中将看见输出了当前目录下的文件:

同理,可以执行绝大部分在终端中执行的命令,不过有些程序所需要的实现可能不太一样,比如更新软件包,则需执行如下命令:

sudo -S apt-get update

如果不带参数”-S”,则会返回错误信息:“sudo:没有终端存在,且未指定 askpass 程序”

因此此种方法启动程序的时候如果需要 root 权限,则需要在”sudo”后加上选项”-S”。

还有的情况就是因为终端启动的时候其实已经帮我们读取了很多环境变量,但是我们在 QT 程序中直接启动 bash 的时候这些环境变量尚未被读取,导致一些程序无法启动,报错“未找到命令”。这时需要我们主动去 source 一遍对应的环境。

  • 善后

QProcess 启动的外部程序并不会随着 QT 程序的关闭而关闭,所以在窗口的销毁函数中加入以下代码,使得窗口销毁时连带终结外部进程。

if(cmd)
{
      cmd->close();
      cmd->waitForFinished();
}
说你懂得生之微末,我便做了这壮大与你看,你说再热闹也终需离散,我便做了这一辈子与你看,你说冷暖自知,我便做了这冬花夏雪与你看,你说恋恋旧日好时光,我便做了这描金绣凤的浮世绘与你看。你说应愁高处不胜寒,我便拱手河山,讨你欢。