Qt中执行终端命令和执行shell脚本文件是一个常见需求,一般可以在c++中直接调用system()实现执行终端命令,shell脚本同样也可以,但是会阻塞程序。实际上更推荐使用Qt中提供的QProcess,高度封装好的功能,拥有非阻塞的优点。
但是我在网上看了很多博客,内容大多数互相转载搬运甚至抄袭,如果跟着大多数博客去使用QProcess的话,分分钟踩坑和浪费时间调试。
很多方法都是教人这么用QProcess,基本会程序阻塞,而且得不到想要的输出结果。
QProcess process;
process.start(bash);
process.write("hello.sh");
process.waitForFinished(); //或者用waitForStarted()函数
QByteArray output = process.readAllStandardOutput();
qDebug()<<output;
ui->paintText->appendPlainText(output);
看到这种直接使用waitForFinished的或者waitForStarted函数的方法的,请及时避雷。
有的方法会使用lambda去写connect连接信号和槽,同样不好用,不是标准的使用方法。
想真正非阻塞地使用QProcess,老老实实按照连接信号与槽的方法去使用。下面介绍标准使用流程:
class MainWindow : public QMainWindow
{
public:
...
private:
QProcess* process; //创建私有Qprocess变量,供MainWindow内部调用
}
MainWindow::MainWindow
{
...
process = new QProcess();
...
}
class MainWindow : public QMainWindow
{
public:
...
public slots:
void processOuptutSlot();
private:
...
}
void MainWindow::processOuptutSlot()
{
//输出终端信息
qDebug()<<process->readAllStandardOutput();
}
MainWindow::MainWindow
{
...
//readyReadStandardOutput是QProcess提供的信息,具体查阅QT助手
QObject::connect(process, SIGNAL(readyReadStandardOutput()), this, SLOT(processOutputSlot()));
...
}
//通常在某个按钮的槽函数或者某个函数中调用process执行命令
{
...
process->start("bash");
process->write("./home/hello.sh\n"); //使用sh脚本的路径,结尾必须加上\n,代表回车
//或者尝试使用别的命令
//prcess->write("ls\n");
}
只要命令有输出,就会不断激活readyReadStandardOutput信号(通常不止一次),然后执行槽函数输出信息,输出信息完结了就不会激活readyReadStandardOutput信号了。整个过程非阻塞。