我對 Qt 很陌生。
我創建了一個帶有運行和取消按鈕的小部件。Run 通過 QProcess 啟動 bash 腳本,Cancel 按鈕用于發送 SIGINT 信號以中斷 bash 中的行程(無法正常作業)。
啟動腳本的 QProcess 在我的建構式中宣告并連接到附加函式:
runScript = new QProcess;
connect(runScript , SIGNAL(readyReadStandardError()), this, SLOT(updateProcessError()));
connect(runScript , SIGNAL(readyReadStandardOutput()), this, SLOT(updateProcessText()));
其中附加槽只是更新 log 和 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腳本正在終端上輸出,以及錯誤,但僅在腳本完成后。
所以當腳本運行時,一切都被凍結了,我什至不能點擊取消按鈕。
所以第一個問題是:如何實時附加 QPlainTextEdit,通過從終端讀取 QProcess 輸出來完成附加?
我知道為什么我的取消按鈕不起作用,并且我對解決方案有一個想法。運行按鈕啟動runScript行程并等待它完成。因此,在腳本完成之前,插槽自然無法完成。我覺得我的實作中的問題是我將運行按鈕捕獲到終端上運行的 QProcess 中。我可以嘗試找出一種 bash 方式來輸出腳本的輸出和錯誤以記錄檔案或分叉腳本執行并對其行程執行某些操作,但我想要關于如何正確執行此操作的建議(我只從 Qt 10 開始幾天前所以一切都是新的)。我想如果我最后用 & 運行我的腳本,我可以以某種方式弄清楚如何從 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 中將腳本作為單獨的行程啟動,并在“取消”按鈕上提取 shell 行程 ID 并殺死它。如果我這樣做,我將如何訪問在 qt 中運行腳本的行程的輸出?我想要最佳答案。
uj5u.com熱心網友回復:
正如檔案所說,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://www.uj5u.com/houduan/434944.html
