Search code examples
javamultithreadingswingjtextareaevent-dispatch-thread

Appending to JTextArea from another Class


my Reader class is used to display server messages whenever the server sends one. This code works perfectly when printing directly to the command line, I receive ever message sent by the server. However, the JTextArea only shows every other line or so. I am not sure what to do here. I read something about InvokeLater, but I am unsure if this is the correct situation to use it.

Also, the Thread is started from a GUI class when I click the connect button.

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();
        }
    }
}

Thank you for your replies and examples. I have added the following to the checker() method :

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

The same problem exists (receives only every other server message) but now it locks up on every other message. If my server send 4 messages, it skips the first one gets the second etc.. Thank you for your help!


Solution

  • You're reading from the BufferedReader twice:

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

    So that's why you're only seeing every other line. Your program likely freezes due to your trying to call readLine() on the event thread -- don't do that.

    Only read from the BufferedReader once for each line. I'd also change the while loop, and would do the buffered reader's read outside of the 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();
       }
    

    Or better -- use a SwingWorker object and publish/process the line to your JTextArea.

    As an aside, you'll want to learn about and have your code comply with Java naming conventions including having all class names start with an upper case letter and all variables and methods begin with a lower case letter. Doing this will allow others to more easily and quickly understand your code, and will likely help you get quicker and better help here.