9

PyQt で GUI を開発しています。GUI には、qListWidget、qTableWidget、および Mayavi で実装されたプロットがあります。このリストは、プロットされる形状 (円柱や円錐など) を参照します。リストで形状が選択されている場合、形状のプロパティが (辞書変数から) テーブルに読み込まれ、形状がプロットで強調表示されるようにします。Mayavi プロットが正常に動作しています。また、テーブルが編集された場合は、形状を再プロットして、新しいプロパティ値を反映する必要があります (半径が変更された場合の円柱のように)。

したがって、リスト項目が選択されている場合 -> (辞書変数から) 項目のプロパティでテーブルを更新し、プロット上の項目を強調表示します

テーブルが編集された場合 -> 辞書変数を更新し、アイテムを再プロットします

問題: リスト項目を選択してテーブルにデータをロードすると、セルが更新されるたびに qTableWidget ItemChanged シグナルが発生し、不完全なデータで何度も形状を再プロットすることになります。

テーブルがプログラムによって更新されている間に GUI イベント ループを無効にする一般的な方法はありますか? (私は Excel VBA の経験があります。そのコンテキストで Application.EnableEvents=False を設定すると、セルがプログラムによって更新されるたびに WorksheetChange イベントがトリガーされるのを防ぐことができます。)テーブルは更新されていますか?アイテムごとではなく、一度にテーブル ウィジェットを更新する方法はありますか? (私は意図的に Model-View フレームワークを今のところ避けていることを認めます。したがって、qListWIdget と qTableWidget です)。

助言がありますか?

私は初めての投稿者ですが、StackOverflow の長年のユーザーです。このような素晴らしいコミュニティであることを前もって感謝したいと思います。

4

3 に答える 3

15

blockSignals(bool)とそのサブクラスがシグナルを発するのを抑制QObjectsし、他のオブジェクトがスロットでそれらを受信できないようにすることを目的としています。しかし、これはQObject方法です。スロット内で計算やその他の高価な処理をトリガーする可能性がある、変更に応答して 1 つのオブジェクトがシグナルを発しないようにする場合は、これが必要です。

しかし、変更を繰り返し行うことでコストのかかるペイント操作が何度も発生する (または、ウィジェットで他のコストのかかるイベントが生成される) 場合は、 で更新を無効にすることができますupdatesEnabled(bool)。このメソッドの利点は、ターゲット ウィジェットの子を再帰的に無効にし、それらも更新されないようにすることです。したがって、再度有効にするまで、階層内の更新は何も受信されません。

mainWidget.setUpdatesEnabled(False)
# do a bunch of operations that would trigger expensive events
# like repaints
mainWidget.setUpdatesEnabled(True)

最終的には、問題の原因がシグナルのトリガーにあるのか、ウィジェット イベントのトリガーにあるのかによって異なります。シグナルをブロックしても、ウィジェットはイベントを処理できますが、他のリスナーには通知されません。updatesEnabled多数のリスト/テーブル/ツリーの更新をラップする一般的な方法です。後で再度有効にすると、単一の投稿更新が実行されます。

于 2012-12-08T20:22:16.773 に答える
11

を継承する任意のオブジェクトのシグナルを一時的にブロックQObjectできます。

self.tableWidget.blockSignals(True)
# perform updates, etc
self.tableWidget.blockSignals(False)
于 2012-12-07T22:59:43.240 に答える
0

イベント ループ全体を無効にすると、アプリが応答しなくなります。また、ユーザーが気付かなくても、OS は何らかの「ハング」通知を表示する場合があります (OS X の鮮やかな色の回転するビーチボールのように、ユーザーは見逃すことはありません)。

イベント ループを完全に無効にすることなく、再描画を無効にしたい場合があります。しかし、それでもおそらくあまりにも劇的です。

あなたが実際にやろうとしているのは、テーブルが再描画を停止することを確認することだけです(テーブルビューを実装した方法を変更することなく、理想的ではないと認めますが、理由があります)。

そのため、ItemChanged の更新を無効にするだけです。ほとんどの場合、これを行う最も簡単な方法はblockSignals(True)、ウィジェットを呼び出すことです。

これが機能しないまれなケース (または、Qt4 ベースのプロジェクトと以前のプロジェクトの両方で使用されることを意図した古いコードを扱っている場合) では、シグナルのハンドラーを取得して隠しておくことができます。離れてそれらを削除し、作業を行ってから、以前のハンドラーを復元します。

代わりに、ハンドラーがアクセスできるフラグを作成し、フラグが設定されている場合は何もしないように変更することができます。これは伝統的な C のやり方ですが、通常は Python でやりたいことではありません。

于 2012-12-07T22:25:32.780 に答える