请考虑以下逻辑流程:
1. App started
2. functionA() triggered
3. the app periodically capture some images to external files
4. end of functionA()
5. the app create a video from captured images, using ffmpeg as external program
6. [step 2 -> step 5] may be repeated.
7. App quit
Run Code Online (Sandbox Code Playgroud)
为了实现这个流程,我使用QProcess启动外部程序让我加入图像,但是我对QProcess的正确使用模式感到困惑.(我不关心ffmpeg的控制台消息,我通过检查是否创建了视频文件来确定步骤5的成功.)
尝试1
void MyWidget::createAVI()
{
checkAndDeleteAVI();
process = new QProcess(this); // process_ defined as class member;
process->start("ffmpeg -f images2 ....");
process->waitForFinished(-1); // (a)
// (b)
}
Run Code Online (Sandbox Code Playgroud)
在(a),我读了这个调用可以冻结主GUI的文档,所以我应该从QThread/QRunnable调用吗?
在(b),我错过了什么吗?当我试图关闭应用程序时(流程中的第7步),应用程序崩溃了,我认为生成的QProcess没有正确发布.
尝试2
我编写了一个QProcess的包装类,如下所示:
Launcher.h
class Launcher : public QObject
{
Q_OBJECT
public:
/** constructor */
explicit Launcher(QObject *parent = 0);
/** destructor */
~Launcher() {
if (started_ && process_->state() != QProcess::NotRunning)
process_->kill();
} // end_dtor(Launcher)
Q_SIGNALS:
void feedbackLog(QString log);
public Q_SLOTS:
void launch(QString program, QStringList argList);
private:
QProcess * process_;
bool started_;
private Q_SLOTS:
void error(QProcess::ProcessError error);
void finished(int exitCode, QProcess::ExitStatus status);
void stateChanged(QProcess::ProcessState state);
}; // end_class(Launcher)
#endif // LAUNCHER_H
Run Code Online (Sandbox Code Playgroud)
Launcher.cpp
#include "launcher.h"
#include <QCoreApplication>
#include <QtDebug>
Launcher::Launcher(QObject *parent) : QObject(parent), started_(false)
{
process_ = new QProcess(this);
connect(process_,
SIGNAL(error(QProcess::ProcessError)),
SLOT(error(QProcess::ProcessError)));
connect(process_,
SIGNAL(finished(int, QProcess::ExitStatus)),
SLOT(finished(int, QProcess::ExitStatus)));
connect(process_,
SIGNAL(stateChanged(QProcess::ProcessState)),
SLOT(stateChanged(QProcess::ProcessState)));
} // end_ctor(ExternalLauncher)
void Launcher::launch(QString program, QStringList argList)
{
started_ = true;
process_->start(program, argList);
process_->waitForFinished(-1); // (c)
Q_EMIT feedbackLog(process_->readAllStandardOutput());
process_->close();
} // end Launcher::launch()
void Launcher::error(QProcess::ProcessError error)
{
/* just feedback some text about the error */
} // end_slot(Launcher::error)
void Launcher::finished(int exitCode, QProcess::ExitStatus status)
{
started_ = false;
/* feedback some text about finished */
} // end_slot (Launcher::finished)
void Launcher::stateChanged(QProcess::ProcessState state)
{
qDebug() << "Luancher::stateChanged" << state;
}
Run Code Online (Sandbox Code Playgroud)
我如何使用启动器:
void MyWidget::createAVI()
{
checkAndDeleteAVI();
launcher_.launch("ffmpeg", "argsList"); // launcher_ defined as class member;
}
Run Code Online (Sandbox Code Playgroud)
那么,在(c),是否没有必要waitForFinished()?(因为我读了一些信息,我不应该混淆waitForXXX()和QProcess的信号/插槽框架)
另外,Launcher课程中是否有一些我错过的东西,因为我在使用这种方法时也会遇到应用程序崩溃.
主要问题:一般来说,何时调用QProcess :: terminate()/ QProcess :: kill(),何时删除QProcess对象?
谢谢
您不需要waitForFinished(),您会收到有关它的信号,所以为什么还要等待呢?相反,您可能想要waitForStarted()确保launch()该过程已成功启动。当然,在这种情况下,您需要改变使用您的方式Launcher- 不要在之后立即销毁它launch()。
如果该过程已完成,则无需terminate()/kill()该过程,仅当您需要提前停止它时。您可以在收到finished()或error()发出信号时删除它process_->deleteLater()(您不能仅delete process_在您处于插槽中时)或在您的 中~Launcher(),前提是在该过程完成之前不会调用它。
| 归档时间: |
|
| 查看次数: |
13151 次 |
| 最近记录: |