2

我的 Reader 类用于在服务器发送消息时显示服务器消息。此代码在直接打印到命令行时完美运行,我收到服务器发送的任何消息。但是,JTextArea 仅显示每隔一行左右。我不确定在这里做什么。我读了一些关于 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 条消息,它会跳过第一个得到第二个等等。谢谢您的帮助!

4

1 回答 1

1

您从 BufferedReader 读取两次:

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

所以这就是为什么你只看到每隔一行。由于您试图调用readLine()事件线程,您的程序可能会冻结——不要那样做。

每行仅从 BufferedReader 读取一次。我还将更改 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 回答