2013-04-30 85 views
5
的正確使用
  • 平臺的:Qt 4.8.2,Win 7的

請考慮以下邏輯流:QProcess中

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 

爲了實現流,我用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) 
} 

在(一)我讀過這個調用可以凍結主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 

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

我如何使用啓動器:

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

所以,在(c),是不是沒有必要waitForFinished()? (因爲我讀了一些信息,我不應該混淆爲QProcess waitForXXX()和信號/插槽框架)

此外,有沒有我錯過的啓動類,因爲我也遇到應用程序崩潰時使用此方法。

主要問題:一般來說,何時調用QProcess :: terminate()/ QProcess :: kill(),以及何時刪除QProcess對象?

感謝

回答

2

你不需要waitForFinished(),您會收到信號有關,所以爲什麼還要等待?相反,您可能需要launch()中的waitForStarted()以確保該過程已成功啓動。當然,在這種情況下,您需要更改使用Launcher的方式 - 不要在launch()之後將其銷燬。

如果過程完成,則不需要terminate()/kill()過程,只有在需要過早停止過程的情況下。您可以在收到finished()error()信號時使用process_->deleteLater()(您不能在插槽中插入delete process_)或在您的~Launcher()中刪除它,前提是在該過程完成之前不會調用它。