【问题标题】:Qt - How to redirect QProcess' stdout to TextEditQt - 如何将 QProcess 的标准输出重定向到 TextEdit
【发布时间】:2015-12-12 21:32:10
【问题描述】:

我正在尝试使用wget 打印下载网站的过程输出 在小部件 (textEdit) 中,但它什么也不打印,但是在终端中它可以工作。

示例

命令:

wget --no-clobber --convert-links --random-wait -r -p -E -e robots=off -U mozilla http://site/path`

输出:

Resolving ******... 54.239.26.173
Connecting to *****|54.239.26.173|:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: unspecified [text/html]
Saving to: ‘/index.html’
...

我的代码:

void downloadWebsite::on_pushButton_clicked()
{
    input = ui->lineEdit->text();
    if(input.isEmpty())
    QMessageBox::information(this,"Error","Not an url / webpage !");
    else{
        QProcess *getDownload = new QProcess(this);
        getDownload->setProcessChannelMode(QProcess::MergedChannels); //it prints everything , even errors
        QString command = "wget --no-clobber --convert-links --random-wait -r -p -E -e robots=off -U mozilla " + input;
        getDownload->start("sh",QStringList() << "-c" <<"cd ;"+command);


        QByteArray outputLog = getDownload->readAllStandardOutput();
        getDownload->waitForFinished();
        getDownload->close();

        QString outputToString(outputLog);
        ui->textEdit->setText(outputToString);

    }
}

我做错了什么?

谢谢。

【问题讨论】:

    标签: c++ qt stdout qprocess


    【解决方案1】:

    连接到信号readyReadStandardOutput。更像这样的东西(但未经测试):

    connect(getDownload, SIGNAL(readyReadStandardOutput()), this, SLOT(readOutput()));
    

    当然 connect 应该在开始之前调用。和信号处理程序:

    void downloadWebsite::readOutput(){
        while(getDownload->canReadLine()){
           ui->textEdit->setText(getDownload->readLine());
        }
        // somebuffer.append(getDownload->readAllStandardOutput());
    }
    

    正如你所见,canReadLine 应该被调用,所以 getDownload 必须可用。

    【讨论】:

    • 嗨,它仍然没有打印任何内容。
    • 我设法让它工作,显然问题是我有 getDownload->waitForFinished();和 getDownload->close();。这取消了我的输出。谢谢。
    【解决方案2】:

    我找到了一些解决方案。 (我是 Qt 新手,但希望它会有所帮助):

    mainwindow.h

    namespace Ui {
    class MainWindow;
    }
    
    class MainWindow : public QMainWindow
    {
        Q_OBJECT
    
    public:
        explicit MainWindow(QWidget *parent = 0);
        ~MainWindow();
    
    signals:
        void proccessFinished(int exitCode, QProcess::ExitStatus status);
    
    public slots:
        void runCommand();
        void readCommand();
        void stopCommand(int exitCode, QProcess::ExitStatus exitStatus);
    
    //private or public?
    private slots:
        void error(QProcess::ProcessError error);
        void stateChanged(QProcess::ProcessState state);
    
    private:
        Ui::MainWindow *ui;
        QProcess *cmd;
    };
    

    mainwindow.cpp

    include "mainwindow.h"
    include "ui_mainwindow.h"
    include <QDebug>
    
    MainWindow::MainWindow(QWidget *parent) :
        QMainWindow(parent),
        ui(new Ui::MainWindow)
    {
        ui->setupUi(this);
        cmd = new QProcess(this);
        cmd->setProcessChannelMode(QProcess::MergedChannels);
        //button click
        connect(ui->btnRun, SIGNAL (clicked()), this, SLOT (runCommand()));
        // process has some data to read
        connect(cmd, SIGNAL (readyRead()), this, SLOT (readCommand()));
        //process finished
        connect(cmd, SIGNAL (finished(int, QProcess::ExitStatus)), this, SLOT (stopCommand(int, QProcess::ExitStatus)));
    }
    
    MainWindow::~MainWindow()
    {
        delete ui;
        cmd->close(); //? how to do it right?
        delete cmd;
    }
    
    
    void MainWindow::runCommand()
    {
        ui->output->append("Run process...");
        cmd->start("ping -n 15 google.com");
        // ??? the best way to continue here???
    }
    
    void MainWindow::readCommand(){
        ui->output->append(cmd->readAll()); //output is QTextBrowser
    }
    void MainWindow::stopCommand(int exitCode, QProcess::ExitStatus exitStatus){
        ui->output->append(cmd->readAll());
        ui->output->append("cmd finished");
        ui->output->append(QString::number(exitCode));
    }
    
    void MainWindow::error(QProcess::ProcessError error)
    {
           qDebug() <<"Error" << error;
    }
    
    void MainWindow::stateChanged(QProcess::ProcessState state)
    {
        qDebug() << "Process::stateChanged" << state;
    }
    

    【讨论】: