PyQt はイベントベースです。イベントを待機しているループを継続的に実行しており、関心のあるイベントを取得すると、コールバックを呼び出します (またはスロットにシグナルを送ります)。ですから、「入力があるまでブロックする」と直接言う方法はありません。
しかし、その時点に到達する前に、シミュレーションがメイン スレッドでループを継続的に実行している場合、PyQt もメイン スレッドでループを継続的に実行することはできません。そのため、「ウィンドウの更新」や「終了」などの OS からのイベントには応答できません。ユーザーに関する限り、アプリは凍結されています。彼女は常に人気のあるビーチボール (または他のプラットフォームに相当するもの) しか見ることができません。
しかし、最初の問題を解決することを選択すると、2 番目の問題のほとんどがほぼ無料で解決されます。
GUI アプリがフリーズする理由は、GUI ライブラリの例として Tkinter を使用して、問題全体と考えられるすべての解決策を一般的に説明しようとする試みです。より Qt 固有のものが必要な場合は、Qt チュートリアルにセクション全体があると確信していますが、どこにあるかはわかりません。頭の中で少し C++ を Python に変換する必要があるかもしれません。
ただし、コールバックまたはスレッドという 2 つの主要なオプションがあります。
まず、ループを小さな断片に分割できます。それぞれの断片は数ミリ秒しかかかりません。ループ全体を実行する代わりに、最初の部分を実行し、その最後の行として、次の部分をできるだけ早くスケジュールするように PyQt に要求します (たとえば、QTimer
タイムアウト 0 で a を使用します)。これで、Qt は数ミリ秒ごとにイベントをチェックできるようになり、何もすることがなければ、すぐに作業の次のステップを開始します。
適切なサイズのチャンクを生成するイテレータ (またはプッシュ コルーチン) を中心にフロー コントロールが既に構築されている場合、これは非常に簡単です。そうでない場合は、外側のループのフロー制御を裏返しにすることを意味する可能性があり、理解するのが難しい場合があります。
では、これを行った後、どのようにしてユーザー入力を取得するのでしょうか? 単純:
- を呼び出す場所
raw_input
では、コードの次の部分をスケジュールする代わりに、適切な GUI 操作を行います。ポップアップ メッセージ ボックスを作成し、テキスト入力コントロールとボタンを再表示します。
- コードの次の部分を、ボタンのクリックまたはメッセージボックスの受け入れなどのシグナルのハンドラーとして接続します。
または、バックグラウンド スレッドで作業を実行することもできます。これには何も再編成する必要はありませんが、スレッド間で何も共有しないように注意する必要があります。残念ながら、これにはバックグラウンド スレッドから GUI ウィジェットのメソッドを呼び出すことも含まれます。幸いなことに、PyQt にはこれを非常に簡単に処理するメカニズムがあります。シグナルは、必要に応じてスレッド間で自動的にルーティングされます。
では、このシナリオでユーザー入力を求めるにはどうすればよいでしょうか。
- の後のすべてを別の関数に分割し、シグナル
raw_input
のハンドラーとして接続します。got_input
- を呼び出していた元の関数では、
raw_input
代わりにgimme_input
シグナルを発行します。
- そのシグナルのハンドラーを
gimme_input
メイン スレッドで実行するように記述します。これにより、GUI ウィジェットが表示されます (上記のシングル スレッドの例と同様)。
got_input
ワーカー スレッドにシグナルを送信する [OK] ボタンのハンドラーを記述します。