JTextArea gets append but does not display text

5

I'm having trouble using a JTextArea. I need every time something happens on my system, an info is added in real time. However, it does not appear anything.

I've tried to use setText() and append() , but neither worked. However, if I do this here

JOptionpane.showMessageDialog(null, JtextArea.getText())

It returns everything I had written before but was not showing up in it. I've already tried using repaint() too and nothing.

Has anyone ever been through this?

Here's a piece of code. When I click on a button, it has this call:

    if (!isStartServer()) {
        area.append("Iniciando servidor de aplicação...\n");
        Integer portaSocket = Integer.parseInt(tfPorta.getText());
        Integer limite = Integer.parseInt(tfLimite.getText());

        setStartServer(true);
        StartServidor s = new StartServidor(portaSocket, limite, this);
        new Thread(s).start();

        btStart.setText("Stop Server");
    }else{
        System.exit(0);
}

In this way, StartServer has become a Thread, which is usually where I will write the messages in JtextArea. When I did not have this "StartServer" as a Thread, it did not update the JtextArea when I called the writeTextArea (String msg);

StartServer Code:

  public void run() {

    setPortaSocket(getPortaSocket());
    setLimite(getLimite());

    try {

        setServerSocket(new ServerSocket(getPortaSocket()));
        writeTextArea("Ouvindo a porta " + getPortaSocket() + "...");

        while (servidor.isStartServer()) {
            setSocketCliente(getServerSocket().accept());

            setUser(new User());
            getUser().setCliente(getSocketCliente());

            scanner = new Scanner(getUser().getCliente().getInputStream());

            if (scanner.hasNext()) {
                getUser().setNome(scanner.nextLine());
            }

            writeTextArea(getUser().getNome() + " conectou-se.");

            if (!clientes.containsKey(getUser().getNome())) {
                clientes.put(getUser().getNome(), getUser());

                getUser().setIpComputador(getUser().getCliente().getInetAddress().getHostAddress());
                getUser().setNomeComputador(getUser().getCliente().getInetAddress().getHostName());

                ServidorReadMessage read = new ServidorReadMessage(getUser(), this);
                new Thread(read).start();
            }

        }

    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        try {
            if (getServerSocket() != null) {
                getServerSocket().close();
            }
            if (getSocketCliente() != null) {
                getSocketCliente().close();
            }
            if (scanner != null) {
                scanner.close();
            }
        } catch (IOException e) {
        }
    }
}

In this way, you are writing correctly, but I do not know if it is the best way, I do not know nor do I know if it is correct to do so. So I'd like your help. I've looked at the documentation and it says nothing about it.

    
asked by anonymous 11.07.2014 / 18:28

2 answers

4
  

When I click a button, it has this call:

All code executed in response to a click of a button executes in the Event Dispatcher Thread . This thread is used for just about everything that interfaces with the Swing library. So, if you have a code:

void actionPerformed(ActionEvent e) {
    // Código
}

As long as this code does not finish Swing, it will not do anything else (repainting screens, updating components, etc.).

  

In this way, StartServer has become a Thread, which is usually where I will write the messages in JtextArea. When I did not have this "StartServer" as a Thread, it did not update the JtextArea when I called the writeTextArea (String msg);

In fact, before you moved your code to a separate thread, the loop waiting for new connections ran in the Event Dispatcher Thread . That means that% w / w never returned! He would stand still, waiting for the socket connections, and with that Swing would do nothing else. When you tried to use actionPerformed in JTextArea, it updated its model ( setText ) but did not move the view. So, if you did:

area.getText();

It would give you the updated content (because the template was updated), but if you looked at the text box on the screen you would only see the old value (since the screen refresh is Event Dispatcher Thread , and it is stopped waiting for your code to finish executing).

  

In this way, you are writing correctly, but I do not know if it is the best way, I do not know nor do I know if it is correct to do so.

Yes, that way is correct. But the best way would be to use Document : a thread type specific to tasks started via Swing. Here's a documentation describing its use and benefits. But if you want to keep doing it the way you are, you have no problem.

Detail Important: The vast majority of Swing library methods are not thread-safe . This means that - if you need to change some component from another thread (including the main thread ), you should do so. using one of the special methods of SwingWorker . Example:

// Seu thread (ou main thread)

/* area.setText("texto"); // ERRADO */
SwingUtilities.invokeLater(new Runnable() {
    public void run() {
        area.setText("texto"); // Certo
    }
});

// Event Dispatcher Thread

area.setText("texto"); // Certo
    
13.07.2014 / 07:00
1

Your code for the writeTextArea(String msg) method might look like this:

private void writeTextArea(String msg){
    area.setText(area.getText()+msg+"\n");
    area.repaint();
}

Basically it defines the text of your JTextArea for any text that was already inside, adds the message and renders the JTextArea again. If it does not work, I have no idea what it is, and the JVM itself should render the component again if it has been modified.

    
12.07.2014 / 01:23