2017-09-14 31 views
0

大きな計算を実行するQThreadベースのコードを書きました。進行状況を視覚化するには、QProgressDialogを開く必要があります。ダイアログは、計算中にメインウィンドウの変更を許可したくないので、アプリケーションモーダル(open()を使用)です。スレッドは、GUIとスレッドとの間のステートマシンベースの通信を可能にする様々な信号を発信する。Modal QProgressDialog :: setValue()はネストされたイベントループによってクラッシュする

スレッドのワーカーオブジェクトによって生成された2つの信号は、「進捗状況」と「終了済み」です。 "Progress"が発生した場合は、setValue()を使用してQProgressDialogを更新しています。 「Finished」が発行された場合、ダイアログは破棄されます。

  • のsetValue(100)直後に放出される "終了" 放出される "進行" イベント(100%)と呼ばれている起因する:

    以下は計算の終了時に起こります"進行" イベント

  • ダイアログがモーダルであるためには、setValueのは()のprocessEventsを()
  • のprocessEvents() "完了" イベントを提供して呼び出す
  • 「完了」イベントは、ダイアログがクラッシュ

QProgressDialogはsetValueの中で()のprocessEventsを呼び出すことで、私のアーキテクチャを壊すの()を引き起こすのsetValueの真ん中 ()で破壊されます。また、私のコーディング規則は、ネストされたイベントループ(exec()などのような)の使用を禁止しています。

  1. はなぜモーダルダイアログは、ネストされたイベントループを必要としない:

    私は2つの質問がありますか?親のウィンドウの入力を阻む私の邪魔にならないものから、これを必要としないようです。

  2. QProgressDialogはモーダルな方法で使用できますが、ネストされたイベントループはありませんか?

+0

ダイアログを「破壊する」のはどうですか?あなたは 'deleteLater()'を使っていますか? – Mike

+0

質問のタイトルがあなたの実際の番号付き質問と一致しません。それらを同じにしてください。 – xaxxon

+0

@Mike:削除を利用します。おそらくdeleteLaterが回避策ですが、私はできるだけ早くこれを試していきます。 – Silicomancer

答えて

1

あなたはQProgressDialogを破壊するためにdeleteLater()を使用する必要があります。 QProgressDialogオブジェクトを削除するイベントは、QProgressDialogオブジェクト自体に属する関数内で処理されます。これは、C++メンバ関数内でdelete this;を呼び出す正当性を示します。詳細については、isocpp C++ FAQのthis questionを参照してください。 。その要旨は、あなたがQtのQProgressDialog::setValue()実装でこれを保証できないため、...あなたは、もはや自殺コミット後のオブジェクトのいずれかのメンバにアクセスしないことを

を保証するイベントdeleteQProgressBarのようなものということですこれは、オブジェクトの任意のメンバーへの次のアクセス時にUBをうまく呼び出すようになります(メンバー関数内で取得されたとき)。 deleteLaterは、遅延削除イベントが特別な方法で処理されるため(QCoreApplication::processEvents()で取得されない)、この種の問題を解決するように特別に設計されています。これはsetValueリターンがイベントループにしていないsetValueの実行の途中で制御した後QProgressDialogオブジェクトは常にこのような状況でdeleteLaterを使用して...

を破壊されることを意味します。イベント内でプレーンdeleteを使用する場合は、このオブジェクトのメンバー関数を実行している間にこのイベントが処理されないこと、およびこのオブジェクトからの信号を放出した結果として実行されないことを確認する必要があります結局のところ、シグナルはQtのMOCによって実装されているメンバ関数なので)...

+0

setModal()/ show()はここでは機能しません。私はすでにopen()を使用しています。 QProgressDialogは、私が使用するモダリティの種類にかかわらず、とにかくsetValue()のイベントループを呼び出すため、特別です。 – Silicomancer

+0

@Silicomancerさて、ネストされたイベントループは、あなたが記述しているクラッシュとは関係ありません。とにかく、ネストされたイベントループを持たずにモーダルダイアログを設定することについてのあなたの質問に答えました。(あなたの質問が正しいのですか?) 'open()'を使って別の方法にもなっています... – Mike

+0

申し訳ありません、Mike、私はあなたがその質問に答えなかったと思う。私はイベントループなしでモーダルダイアログを設定する方法を知っています。私の質問は、イベントループなしでモーダル* QProgressDialog *をセットアップする方法です。しかし、私はQProgressDialog :: setValue()の特殊な動作のために、それはまったく不可能であると思います。たぶんdeleteLaterは良い回避策です。私は試した後にフィードバックを与えます。 – Silicomancer

関連する問題