Utilisation appropriée de QProcess

  • Plate-Forme: Qt 4.8.2, Win 7

Veuillez considérer ce qui suit la logique de flux:

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

Pour atteindre le flux, j'utilise QProcess pour démarrer le programme externe pour moi de rejoindre les images, mais j'ai confondu avec le bon mode d'utilisation de QProcess. (Je ne me préoccupe pas de messages dans la console de ffmpeg, je déterminer le succès de l'étape 5 par vérifier si le fichier vidéo est créé.)

Tentative 1

void MyWidget::createAVI()
{
    checkAndDeleteAVI();
    process = new QProcess(this); //process_ defined as class member;
    process->start("ffmpeg -f images2 ....");
    process->waitForFinished(-1);  //(a)
    //(b)
}

À (un), j'ai lu la documentation le présent appel peut geler l'interface graphique principale, donc dois-je appeler à partir de QThread/QRunnable?

À (b), suis-je raté quelque chose ici? comme lorsque je tente de fermer l'application (étape 7 du flux), l'application se bloque, et je pensais que les engendré QProcess n'est pas correctement publiés.

Tentative 2

J'ai écrit une classe wrapper de QProcess:

Lanceur.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

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;
}

Comment j'utilise le Launcher:

void MyWidget::createAVI()
{
    checkAndDeleteAVI();
    launcher_.launch("ffmpeg", "argsList"); //launcher_ defined as class member;
}

Ainsi, en (c), qu'il est inutile de waitForFinished()? (comme je l'ai lu quelques infos que je ne devrais pas mélanger waitForXXX() et signal/slot cadre de QProcess)

Aussi, il ya quelque chose que j'ai raté pour le Lanceur de classe, comme je l'ai aussi l'expérience de l'application crash lors de l'utilisation de cette approche.

question Principale: En général, quand appeler QProcess::terminate() /QProcess::kill(), et quand à supprimer le QProcess objet?

Grâce

OriginalL'auteur YamHon.CHAN | 2013-04-30