2016-06-27 18 views
0

C++/QTアプリケーションには「インストーラ」機能があります。すべて正常に機能しますが、プログラムが「コピー処理中」のときにウィンドウの外をクリックすると、何らかの形でがフォーカスを失い、コピー処理が終了するまでがフリーズすると、すべて正常に表示されます。QProgressBarの値は100 %。このような

イムコピー:この機能は、ファイルとQStringList繰り返し処理foreachループで呼び出されフリーズされたアプリケーションを防ぐためにファイルをコピーする

void Installer_C::copy(QString aSrcPath, QString aDstPath) 
{  
    //handles 
    hSrc = CreateFileW(..); //source file 
    hDst = CreateFileW(..); //destination 
    //copy 
    ReadFile(...); 
    LockFile(...); 
    WriteFile(...); //->returnes bytesWritten 
    UnlockFile(...); 
    updateQProgressBar(bytesWritten); //updates progressbar in my application 
    CloseHandle(...); 
} 

は(私のlaunchInstall()機能にあります)。
私の問題のため、スレッドをこのコピープロセス用に作成することを考えました。 Installer_C::copy()コールごとに新しいスレッドを作成するか、launchInstall()関数を呼び出すスレッドを1つだけ作成すると効率的です(多分役に立たないと思います)。
またはより良い質問:アプリケーションがフリーズするという私の問題を解決することすらできますか? ProgressBarがこのスレッドから更新されるように、どうすればいいですか?

答えて

1

私はあなたの問題を解決する最良の方法は、プロセスをコピーする追加スレッドを1つ作成することです。 QThread(Qt documentation:QThread)クラスを使用してファイルをコピーするスレッドを作成することができます。メインスレッドはGUIを実行し、ファイルのコピー中に利用可能になります。

スレッドコピーするための小さな例:もちろん

class CopyThread : public QThread 
{ 
    Q_OBJECT 
private: 
    QStringList oldfiles_; 
    QStringList newfiles_; 
public: 
    CopyThread(const QStringList& oldfiles, 
       const QStringList& newfiles, 
       QObject * parent = 0) 
     : QThread(parent) 
     , oldfiles_(oldfiles) 
     , newfiles_(newfiles) 
    {} 

    void run() Q_DECL_OVERRIDE 
    { 
     int min = qMin(oldfiles_.count(), newFiles.count()); 
     for(int i=0; i<min; ++i) 
     { 
      copyFile(oldfiles_.at(i), newFiles_.at(i)); 
      emit signalCopyFile(oldfiles_.at(i), newFiles_.at(i)); 
     } 
    } 
signals: 
    void signalCopyFile(const QString&, const QString&); 
private: 
    void copyFile(QString aSrcPath, QString aDstPath) 
    { 
     QFile::copy(aSrcPath, aDstPath); 
    } 
}; 

を、あなたはsignalCopyFile(const QString&, const QString&)のためにあなたのウィジェットのスロットを実装し、接続を行う必要があります。コピースレッドを起動して接続を行うために(例えば)小さなコード:

yourSlot
QStringList oldFiles; 
oldfiles.append("C:/1.txt"); 
QStringList newFiles; 
newFiles.append("C:/2.txt"); 
yourProgressBar.setMaximum(oldFiles.count()); 
yourProgressBar.setMinimum(0); 
yourProgressBar.setValue(0); 
CopyThread *copyThread = new CopyThread(oldFiles, newFiles, this); 
connect(copyThread, &CopyThread::finished, copyThread, &QObject::deleteLater); 
connect(copyThread, &CopyThread::signalCopyFile, youWidget, &YouWidget::yourSlot); 
copyThread->start(); 

あなたQProgressBarの値を更新することができます。

void yourSlot(const QString& oldFile, const QString& newFile) 
{ 
    // your actions when one file was copied 
    yourProgressBar->setValue(yourProgressBar.value() + 1); 
} 

すべてがフリーズすることなく、すべての権利になります!

+0

ありがとう、ちょうど 'CopyThread :: run()'を呼びますか?そして、私の場合は、信号が非常に速く放射されているようですが、それらはすべて新しいスレッドに入っていますか?私は思っています:signal emits> copy start>次のシグナルが出ますが、コピーはまだ行われていません。分かりますか? – Drayke

+0

回答を更新します。 1つのファイルがコピーされるたびに信号が放射されます。 –

0

私はQtの中でこの問題を解決するための2つの方法があります知っているように:

  1. QCoreApplication::processEvents()を使用するには。ドキュメントは悪い解決策ではなく、長時間の操作を処理するのに適していると述べています。私はそれがあなたの役に立つと思う。たとえば、各ファイル(または複数のファイル)をコピーした後に呼び出すことができます。
  2. マルチスレッドの使用。これは、GUIスレッドと論理スレッドを分ける大きなアプローチです。キリルのsolutionをあなたの目標に合わせることができます。

だから私の提案は次のとおりです。あなたが簡単かつ迅速ワーキングソリューションが必要な場合は、最初の方法があなたのためです。

あなたはうまく設計、より複雑なアプリケーションを作成し、あなたがもう少しをコーディングする準備ができている第二のアプローチを使用したい場合。

関連する問題