Edy
Edy

Reputation: 5

Cant append to JTextArea

I'm trying to create a text chat with Java. I have a Server and a Client that connect to each other using Streams, and send data using the objectInputStream and objectOutputStream.

I have GUI's for both the client and the server. I made these GUI's using intellij's GUI Form.

server GUI form image

The problem I'm having is when I try to display text to the GUI of the server. I can append to the GUi if I call my relayToAll method from the JTextField actionlistener, which then send the message to all the clients and prints it out in the servers GUI.

If i try to call the same method from where I receive the input, then the append to the text area does not work.

Can anyone tell me why its not appending?

Thanks

public class ServerTest {
private JTextField textField1;
private JTextArea textArea1;
private JPanel Panel;
static private ObjectOutputStream objectOutputStream;
static private ObjectInputStream objectInputStream;
static private Socket client;
static private ArrayList<Socket> clients = new ArrayList<Socket>();
static private ArrayList<ObjectOutputStream> objectOutputStreams = new ArrayList<>();

public void relayToAll(String message){
    try {
        for(int i = 0; i < clients.size(); i++) {
            ObjectOutputStream output = objectOutputStreams.get(i);
            output.writeObject(message);
            output.flush();
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
    appendTextArea(message);
}

public void appendTextArea(String text){
    SwingUtilities.invokeLater(new Runnable() {
        @Override
        public void run() {
            System.out.println("This should go to the Server GUI: " + text);
            textArea1.append(text + "\n");
        }
    });
}

public ServerTest() {

    textField1.addActionListener(e -> {
        System.out.println(e.getActionCommand());
        relayToAll(e.getActionCommand());
        textField1.setText("");
    });
}

public void ReadInput(ObjectInputStream input, int port){
    try {
        String oldMessage = "";
        while (true) {
            String message = (String) input.readObject();
            if (message != oldMessage){
                System.out.println(port + ": " + message);
                oldMessage = message;
                relayToAll(port + ": " + message);
            }
        }
    } catch (IOException e) {
        e.printStackTrace();
    } catch (ClassNotFoundException e) {
        e.printStackTrace();
    }
}


public void IOSetup(){
    try {
        ServerSocket serverSocket = new ServerSocket( 6969 );

        ExecutorService executor = Executors.newFixedThreadPool(5);

        System.out.println("server on\n");
        for (int i = 0; i < 5; i++){

            client = serverSocket.accept();
            clients.add(client);
            System.out.println("Connection from: "+ client.getPort());

            objectOutputStream = new ObjectOutputStream(client.getOutputStream());
            objectOutputStreams.add(objectOutputStream);

            objectInputStream = new ObjectInputStream(clients.get(i).getInputStream());


            executor.submit(() -> {
                ReadInput(objectInputStream, client.getPort());
            });
        }


    } catch (IOException e) {
        e.printStackTrace();
    }

}

public static void main(String[] args) {

    JFrame frame = new JFrame("Server");
    frame.setContentPane(new ServerTest().Panel);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.pack();
    frame.setVisible(true);

    ServerTest application = new ServerTest();


    application.IOSetup();

}

Upvotes: 0

Views: 98

Answers (1)

Hovercraft Full Of Eels
Hovercraft Full Of Eels

Reputation: 285405

Actually you've got kind of a silly mistake. Please check lines (A) and (B) below:

public static void main(String[] args) {
    JFrame frame = new JFrame("Server");
    frame.setContentPane(new ServerTest().Panel); //  *************** (A)
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.pack();
    frame.setVisible(true);
    ServerTest application = new ServerTest();  //  *************** (B)
    application.IOSetup();
}

Do you see a problem? You're creating TWO ServerTest objects, one that has its Panel variable added to the JFrame and that gets displayed, and the other that is set up for IO communication. The ActionListener changes the state of the displayed JTextArea while the IO communications changes the state of a JTextArea that is in the second ServerTest instance, the one not displayed.

One improvement is to create only one instance:

public static void main(String[] args) {

    ServerTest application = new ServerTest();  // create one instance

    JFrame frame = new JFrame("Server");
    // frame.setContentPane(new ServerTest().Panel);

    frame.setContentPane(application.Panel);     // and use in both places

    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.pack();
    frame.setVisible(true);

    //ServerTest application = new ServerTest();
    application.IOSetup();                 // and use in both places
}

Other problems:

  • You've got long-running code long running and blocking in a background thread, and that is potentially dangerous, and the only reason that your GUI is not getting frozen is because you're starting the GUI (incorrectly) on the main thread and off of the Swing event thread. For more on this, you will want to read up on Swing concurrency: Lesson: Concurrency in Swing
  • You will want to learn and use Java naming conventions. Variable names should all begin with a lower letter while class names with an upper case letter. Learning this and following this will allow us to better understand your code, and would allow you to better understand the code of others.

Upvotes: 1

Related Questions