如何实时更新QPlainTextEdit?

How to update QPlainTextEdit in real time?

我是 Qt 的新手。

我创建了一个带有 运行 和取消按钮的小部件。 运行 通过 QProcess 启动一个 bash 脚本,取消按钮用于发送 SIGINT 信号以中断 bash 中的进程(无法正常工作)。

启动脚本的 QProcess 在我的构造函数中声明并连接到追加函数:

runScript = new QProcess;
connect(runScript , SIGNAL(readyReadStandardError()), this, SLOT(updateProcessError()));
connect(runScript , SIGNAL(readyReadStandardOutput()), this, SLOT(updateProcessText()));

其中附加插槽只是更新日志和 logError QPlainTextEdits(也是 MyWidget class 的字段):

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 脚本在终端上输出,伴随错误,但仅在脚本完成后。

因此,当脚本 运行ning 时,一切都被冻结了,我什至无法单击“取消”按钮。

所以第一个问题是:如何实时附加 QPlainTextEdit,其中附加是通过从终端读取 QProcess 输出完成的?

我知道为什么我的“取消”按钮不起作用,并且我有一个解决方案。 运行 按钮启动 runScript 进程并等待它完成。因此,在脚本完成之前,插槽自然无法完成。我觉得我的实现中的问题是我将 运行 按钮捕获到终端上 运行ning 的 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 中断 运行ning shell 脚本,该脚本已在另一个按钮单击时启动?

我觉得一种解决方案是在 bash 中单击 运行 按钮时将脚本作为单独的进程启动,然后在取消按钮上提取 shell 进程 ID 并终止它。 如果我这样做,我将如何访问在 qt 中 运行ning 脚本的进程的输出? 我想要最佳答案。

正如 docs 所说,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。有关详细信息,请参阅 doc