我对Qt很陌生。
我创建了一个具有按钮的小部件。运行通过QProcess启动bash脚本,Cancel按钮将发送SIGINT信号来中断bash中的进程(不能正常工作)。
启动脚本的QProcess在构造函数中声明,并连接到附加函数如下:
runScript = new QProcess;
connect(runScript , SIGNAL(readyReadStandardError()), this, SLOT(updateProcessError()));
connect(runScript , SIGNAL(readyReadStandardOutput()), this, SLOT(updateProcessText()));其中附加插槽只是更新日志和logError QPlainTextEdits (也是MyWidget类的字段):
void MyWidget::updateProcessError()
{
QString output(runScript ->readAllStandardError());
errorLog->appendPlainText(output);
errorLog->verticalScrollBar()->setValue(log->verticalScrollBar()->maximum());};
void MyWidget::updateProcessText()
{
QString output(runScript ->readAllStandardOutput());
log->appendPlainText(output);
log->verticalScrollBar()->setValue(log->verticalScrollBar()->maximum());
}; 现在,这并不是实时的。它会附加所有的输出,shell脚本在终端上输出,沿着错误,但只有在脚本完成之后。
因此,当脚本运行时,所有东西都被冻结了,我甚至不能单击Cancel按钮。
因此,第一个问题是:如何实时添加QPlainTextEdit,其中附加是通过读取终端?的QProcess输出来完成的。
我知道为什么我的取消按钮不工作,我有一个解决方案的想法。Run按钮启动runScript进程,并等待它完成。所以,自然的插槽不能完成,直到脚本完成。我觉得实现中的问题是,我正在将Run按钮捕获到运行在终端上的QProcess。我可以尝试找出一种bash方法来输出脚本的输出和错误,以记录文件或分叉脚本执行,并对它的过程做一些事情,但是我想要一个关于如何正确地这样做的建议(我10天前才从Qt开始,所以一切都是新的)。我想,如果我运行我的脚本,在最后,我可以想出如何从qt (应该被记录)获得它的id,然后取消按钮只需要杀死进程?“运行”按钮的大致位置如下:
void MyWidget::handleRunButton()
{
runButton->setEnabled(false);
QString program = "MyShellScript " + _scriptOptions;
runScript->start("/bin/sh " + program);
runScript->waitForFinished(-1);
}我编写了“取消”按钮以释放SIGINT信号如下:
void MyWidget::handleCancelButton()
{
QProcess *runCtrlC = new QProcess;
runCtrlC->start("/bin/bash -c \" kill -INT $$ \" ");
runCtrlC->waitForFinished(-1);
runScript->terminate();
emit finished(0);
};因此,我的下一个问题是,如何从Qt的一个按钮上中断一个正在运行的shell脚本--单击一下,在另一个按钮上开始单击。
我觉得一种解决方案是在bash中启动脚本,单击Run按钮,然后在Cancel按钮上提取shell进程id并终止它。如果这样做,我将如何访问在qt中运行脚本的进程的输出?我想要最理想的答案。
发布于 2022-02-22 06:32:26
正如文档所说,QProcess::waitForFinished会一直阻塞直到进程完成。删除这一行,它应该会像你期望的那样工作。
void MyWidget::handleRunButton()
{
runButton->setEnabled(false);
QString program = "MyShellScript " + _scriptOptions;
runScript->start("/bin/sh " + program);
// runScript->waitForFinished(-1); <-- DELETE THIS LINE
}编辑:
我漏掉了第二个问题。要终止该进程,只需调用QProcess::kill即可。
void MyWidget::handleCancelButton()
{
runScript->kill();
runScript->waitForFinished(-1);
emit finished(0);
};QProcess::terminate可能也能工作。这取决于你的MyShellScript。有关细节,请参阅文档。
https://stackoverflow.com/questions/71215742
复制相似问题