在QT中启动多个外部控制台应用程序实例并捕获输出?

时间:2020-12-20 23:11:07

I am learning Qt and manged to use the following code from tutorials to launch external application and process output received from it :

我正在学习Qt并且可以使用教程中的以下代码来启动从它接收的外部应用程序和进程输出:

void Dialog::on_startButton_clicked()
{

    QString program = "C:/Program Files/ffmpeg/bin/ffmpeg.exe";
    mTranscodingProcess = new QProcess(this);
    connect(mTranscodingProcess, SIGNAL(started()), this, SLOT(processStarted()));
connect(mTranscodingProcess,SIGNAL(readyReadStandardOutput()),this,SLOT(readyReadStandardOutput()));
    connect(mTranscodingProcess, SIGNAL(finished(int)), this, SLOT(encodingFinished()));


    QStringList arguments;
    QString input = "myfile_path_1";
    QString input2 = "myfile_path_2";

    arguments << "-y" << "-i" << input << "-i" << input2 << "-c" << "copy" << "output.avi" ;

    qDebug() << arguments;

    mTranscodingProcess->setProcessChannelMode(QProcess::MergedChannels);
    mTranscodingProcess->start(program, arguments);
}

This works as expected and I can capture and process output from readyReadStandardOutput() and encodingFinished() slots in my app.

这按预期工作,我可以捕获和处理我的应用程序中readyReadStandardOutput()和encodingFinished()插槽的输出。

Now my question is : How to launch additional jobs of the above and receive separate updates from each instance.

现在我的问题是:如何启动上述的其他作业,并从每个实例接收单独的更新。

1 个解决方案

#1


4  

Launching the additional jobs and receiving updates is easy enough; you just execute the code you posted above multiple times.

启动其他作业和接收更新非常简单;您只需执行多次上面发布的代码即可。

The only slightly tricky part (and I think the core of your question) is how to tell, when your readReadyStandardOutput() (or etc) slot is called, which of the several QProcess objects was the one that called it.

唯一有点棘手的部分(我认为你的问题的核心)是如何判断,当调用readReadyStandardOutput()(或其他)槽时,几个QProcess对象中的哪一个是调用它的那个。

There are several ways to deal with that. In no particular order:

有几种方法可以解决这个问题。没有特别的顺序:

  • You could declare different slots for each QProcess object (e.g. readReadyStandardOutput1(), readReadyStandardOutput2(), etc) and connect each QProcess to different slots. (Not really recommended unless you only have a very small number of QProcesses)

    您可以为每个QProcess对象声明不同的插槽(例如readReadyStandardOutput1(),readReadyStandardOutput2()等),并将每个QProcess连接到不同的插槽。 (除非你只有极少数的QProcesses,否则不推荐)

  • You could create a separate ProcessLauncher class that derives from QObject, and create one ProcessLauncher object for each task you want to launch. Have each ProcessLauncher object create its own QProcess object and connect the QProcess's signals to the ProcessLauncher's slots. Since there is a 1:1 relationship between each ProcessLauncher and its QProcess, the ProcessLauncher would know that its slots were being called by its own QProcess and no other.

    您可以创建一个从QObject派生的单独ProcessLauncher类,并为要启动的每个任务创建一个ProcessLauncher对象。让每个ProcessLauncher对象创建自己的QProcess对象,并将QProcess的信号连接到ProcessLauncher的插槽。由于每个ProcessLauncher与其QProcess之间存在1:1的关系,因此ProcessLauncher会知道其插槽由其自己的QProcess调用而不是其他。

  • You could use a QSignalMapper object to help you differentiate the signals from each other.

    您可以使用QSignalMapper对象来帮助您区分彼此的信号。

  • Or, if you don't mind subverting the object-oriented nature of the signals-and-slots paradigm, your slot methods can call QObject::sender() to find out which QProcess it is that emitted the signal, and alter their behavior based on sender()'s return value.

    或者,如果您不介意颠覆信号和插槽范例的面向对象特性,那么您的插槽方法可以调用QObject :: sender()来找出发出信号的QProcess,并改变它们的行为基于sender()的返回值。

#1


4  

Launching the additional jobs and receiving updates is easy enough; you just execute the code you posted above multiple times.

启动其他作业和接收更新非常简单;您只需执行多次上面发布的代码即可。

The only slightly tricky part (and I think the core of your question) is how to tell, when your readReadyStandardOutput() (or etc) slot is called, which of the several QProcess objects was the one that called it.

唯一有点棘手的部分(我认为你的问题的核心)是如何判断,当调用readReadyStandardOutput()(或其他)槽时,几个QProcess对象中的哪一个是调用它的那个。

There are several ways to deal with that. In no particular order:

有几种方法可以解决这个问题。没有特别的顺序:

  • You could declare different slots for each QProcess object (e.g. readReadyStandardOutput1(), readReadyStandardOutput2(), etc) and connect each QProcess to different slots. (Not really recommended unless you only have a very small number of QProcesses)

    您可以为每个QProcess对象声明不同的插槽(例如readReadyStandardOutput1(),readReadyStandardOutput2()等),并将每个QProcess连接到不同的插槽。 (除非你只有极少数的QProcesses,否则不推荐)

  • You could create a separate ProcessLauncher class that derives from QObject, and create one ProcessLauncher object for each task you want to launch. Have each ProcessLauncher object create its own QProcess object and connect the QProcess's signals to the ProcessLauncher's slots. Since there is a 1:1 relationship between each ProcessLauncher and its QProcess, the ProcessLauncher would know that its slots were being called by its own QProcess and no other.

    您可以创建一个从QObject派生的单独ProcessLauncher类,并为要启动的每个任务创建一个ProcessLauncher对象。让每个ProcessLauncher对象创建自己的QProcess对象,并将QProcess的信号连接到ProcessLauncher的插槽。由于每个ProcessLauncher与其QProcess之间存在1:1的关系,因此ProcessLauncher会知道其插槽由其自己的QProcess调用而不是其他。

  • You could use a QSignalMapper object to help you differentiate the signals from each other.

    您可以使用QSignalMapper对象来帮助您区分彼此的信号。

  • Or, if you don't mind subverting the object-oriented nature of the signals-and-slots paradigm, your slot methods can call QObject::sender() to find out which QProcess it is that emitted the signal, and alter their behavior based on sender()'s return value.

    或者,如果您不介意颠覆信号和插槽范例的面向对象特性,那么您的插槽方法可以调用QObject :: sender()来找出发出信号的QProcess,并改变它们的行为基于sender()的返回值。