0

simpy を使用してシミュレーション ベースのアプリケーションを GUI に変換中です。

プログラムは現在コンソール内で実行され、シミュレーションを実行している simpy はデフォルトで構文のようなループで実行されます。そして、それが私の問題のようです。

現在、コードのコンソール バージョン内で、raw_input() 関数を介してユーザー入力を取得します。これにより、コードを中断して、ユーザーがシミュレーションに必要な値を入力できるようになります。ただし、調査したにもかかわらず、私が構築しているGUI内でpyqtを介してこれを行う同様のクリーンな方法はないようです。

プロセスを異なるスレッドで実行することが唯一の方法でしょうか? そして、もし私がそのアプローチを行うとしたら、それはどのように正確に見え、実際に機能するのでしょうか?

4

1 に答える 1

2

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] ボタンのハンドラーを記述します。
于 2014-07-23T21:50:36.020 に答える