2

私の Reader クラスは、サーバーがメッセージを送信するたびにサーバー メッセージを表示するために使用されます。このコードは、コマンドラインに直接出力するときに完全に機能し、サーバーから送信されたメッセージを受信します。ただし、JTextArea は 1 行おきにしか表示されません。ここで何をすべきかわかりません。InvokeLater について何か読んだことがありますが、これを使用するのが正しい状況かどうかはわかりません。

また、接続ボタンをクリックすると、GUI クラスからスレッドが開始されます。

public class Reader implements Runnable {

    public static Socket s = null;
    public static JTextArea TextArea;
    public static BufferedReader reader = null;

    /*Takes in a Socket. Sets up a input stream.
     * 
     */
    public Reader(Socket sIn, JTextArea display) {
        TextArea=display;
        s = sIn;
        try {
            reader = new BufferedReader(new InputStreamReader(s.getInputStream()));
        } catch (IOException ex) {
            System.out.println("Error in constructor Reader: " + ex);
        }
    }

    public void checker() {
        try {
            /*Sits and waits for a Server Response*/
            while (!reader.ready()) {}

            System.out.println(reader.readLine());
            TextArea.append(reader.readLine()+"\n");

        } catch (Exception ex) {
            System.out.println("checker is crying: " + ex);
        }
    }


    public void run() {
        while (true) {
            checker();
        }
    }
}

回答と例をありがとうございます。checker() メソッドに以下を追加しました。

EventQueue.invokeLater(new Runnable() {
    public void run() {
        try {
            TextArea.append(reader.readLine() + "\n");
        } catch (Exception eee) {
            System.out.println("Error" + eee);
        }
    }
});

同じ問題が存在します (他のすべてのサーバー メッセージのみを受信します) が、他のすべてのメッセージでロックアップします。サーバーが 4 つのメッセージを送信すると、最初のメッセージがスキップされて 2 番目のメッセージが取得されます。ご協力ありがとうございます。

4

1 に答える 1

1

BufferedReader から 2 回読み取っています。

        System.out.println(reader.readLine()); // *** here ***
        TextArea.append(reader.readLine()+"\n");  // *** and here ***

そのため、1 行おきにしか表示されません。イベント スレッドで呼び出そうとすると、プログラムがフリーズする可能性がreadLine()あります。そうしないでください。

行ごとに BufferedReader から 1 回だけ読み取ります。while ループも変更し、バッファリングされたリーダーの読み取りを Runnableの外で行います。

   private String line = ""; // a class field

   public void checker() {
      try {

         while ((line = reader.readLine()) != null) {

            System.out.println(line);
            SwingUtilities.invokeLater(new Runnable() {
               TextArea.append(line + "\n");
            });
         }

      } catch (Exception ex) {
         System.out.println("checker is crying: " + ex);
      }
   }


   public void run() {
      checker();
   }

または、SwingWorker オブジェクトを使用して、行を JTextArea に発行/処理します。

余談ですが、すべてのクラス名を大文字で開始し、すべての変数とメソッドを小文字で開始するなど、Java の命名規則について学び、コードを準拠させる必要があります。これを行うと、他の人がコードをより簡単かつ迅速に理解できるようになり、ここでより迅速かつ適切なヘルプを得るのに役立つ可能性があります。

于 2012-12-01T15:42:47.977 に答える