我正在学习 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);
}
Run Code Online (Sandbox Code Playgroud)
这按预期工作,我可以捕获和处理应用程序中的输出readyReadStandardOutput()和插槽。encodingFinished()
现在我的问题是:如何启动上述的附加作业并从每个实例接收单独的更新。
启动附加作业和接收更新非常容易;您只需多次执行上面发布的代码即可。
唯一稍微棘手的部分(我认为你问题的核心)是如何判断,当你的 readReadyStandardOutput() (或等)槽被调用时,几个 QProcess 对象中的哪一个是调用它的。
有几种方法可以解决这个问题。排名不分先后:
您可以为每个 QProcess 对象声明不同的槽(例如 readReadyStandardOutput1()、readReadyStandardOutput2() 等)并将每个 QProcess 连接到不同的槽。(不推荐,除非你只有很少数量的 QProcesses)
您可以创建一个派生自 QObject 的单独 ProcessLauncher 类,并为要启动的每个任务创建一个 ProcessLauncher 对象。让每个 ProcessLauncher 对象创建自己的 QProcess 对象并将 QProcess 的信号连接到 ProcessLauncher 的插槽。由于每个 ProcessLauncher 与其 QProcess 之间存在 1:1 关系,因此 ProcessLauncher 会知道它的槽是由它自己的 QProcess 调用的,而不是由其他 QProcess 调用的。
您可以使用QSignalMapper对象来帮助您区分彼此的信号。
或者,如果您不介意颠覆信号和槽范例的面向对象本质,您的槽方法可以调用QObject::sender()来找出发出信号的 QProcess,并改变它们的行为基于 sender() 的返回值。