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