0

私は最近取り組んでいるプロジェクトについて多くの質問をしています。これが私がいるシナリオであり、正しい方向への助けや指摘は大いに役立ちます...

これは、サーバーと複数のクライアントで構築されたネットワーク プログラムです。各クライアントには、サーバーから送信されたコマンドに従って動作する必要がある GUI があります。各クライアントは、 と呼ばれるクラス内にラップされますPlayer。これPlayerには GUI (extends JFrame) と main メソッドがあり、サーバーには main メソッドのみ (GUI なし) があります。最初に、このクラスは次のようにメイン スレッドで作成されました。

EventQueue.invokeLater(new Runnable()
{
    public void run()
    {
        new Player().setVisible(true);
    }
 });

クラス全体Playerが EDT で実行されていることに気付くまで、これは正常に機能していました。そのため、サーバーからのコマンドを待つと、そのコマンドが送信されて適切なアクションが実行されるまで、GUI 全体がロックされます。ご想像のとおり、これは恐ろしい設計であり、何かをチェックしたいときはいつでも、GUI が損なわれないように、クレイジーな回避策を見つけなければならないというコーディング環境の本当の苦痛であることが証明されました。

明らかに、別のスレッドでサーバーからのコマンドを確認し、EDT で GUI コンポーネントを実行する必要があります。私の 2 番目の実装には 2 つのクラスがありました。1 つは GUI 用で、もう 1 つはPlayer. アイデアは、次のようなクラスPlayerから GUI にアクセスできるように、GUI を保持する変数を持っているというものでした。Player

class Player
{
    public GUI gui;

    ...

    // And then start this gui inside of the EDT.
    EventQueue.invokeLater(new Runnable()
    {
         public void run()
         {
              this.gui = new GUI().setVisible(true);
         }
    }

this新しいオブジェクトの内部は.ではなくRunnableオブジェクトを参照するため、これも機能しません。RunnablePlayer

Player1 つのスレッド内のクラスと EDT スレッド内の対応する GUI クラスとの間で通信するにはどうすればよいですか?

4

6 に答える 6

3

ポインターの問題を処理するには、次のthisように記述します。

class Player
{
    public GUI gui;

    ...

    // And then start this gui inside of the EDT.
    EventQueue.invokeLater(new Runnable()
    {
         public void run()
         {
              Playser.this.gui = new GUI().setVisible(true);
         }
    }
}
于 2009-04-16T07:45:46.187 に答える
2

Boris Pavlović は構文を正しく理解しています (実際には を削除できますthis.) が、それでもコードは意味を成しません。guiフィールドは、イベントがキューに入れられた後に初期化されるためRunnable、プレーヤー スレッドがそれを使用するのは安全ではありません。

EDT で構築できますPlayer(ただし、EDT からネットワーク操作を行います)。または、GUI を のリスナー (オブザーバー) として登録しPlayerます。invokeAndWait動作しますが、デバッグが困難なデッドロックが時折発生するため、危険です。

于 2009-04-16T08:30:13.367 に答える
1

これを試すことができます:

クラスプレーヤー{パブリックGUI gui;

...

// And then start this gui inside of the EDT.
EventQueue.invokeLater(new Runnable()
{
     public void run()
     {
          Player.this.gui = new GUI().setVisible(true);
     }
}
于 2009-04-16T07:46:41.473 に答える
1

「Player クラス全体が EDT で実行されていることに気付くまで」

コンストラクターは EDT で発生しますが、このクラスで呼び出されるメソッドは発生しない場合があります。

当初の意図どおりにプレーヤー GUI を構築する必要があります。

 EventQueue.invokeLater(new Runnable() 
 {
    public void run()
    {
        new Player().setVisible(true);
    }
 });

ただし、Player はコンストラクターで別のスレッドを起動できます (個人的には、Player 間の接続を共有します)。

もちろん、サーバーからのコールバック メソッドは、可視コンポーネントを変更するときに invokeLater() を使用する必要があります。

于 2009-04-16T11:22:50.213 に答える
1
于 2009-04-16T04:40:17.880 に答える
0

匿名の内部クラスを使用する代わりに、Runnable を実装するクラスを宣言し、引数として GUI インスタンスを取るコンストラクターを持たないのはなぜですか?

また、GUI クラスがスレッド セーフでない場合は、メッセージ キューを使用して EDT とメイン スレッド間の通信を行うことを検討してください。

于 2009-04-16T04:13:05.607 に答える