Jtextarea receives the append but does not display the text

Asked

Viewed 1,540 times

5

I’m having trouble using a Jtextarea. I need that every time something happens on my system, information is added in real time. However, he appears nothing.

I’ve tried using the setText() and the append(), but neither worked. However, if I do it here

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

It returns to me everything that I had written before but that was not appearing in it. I’ve tried to use repaint() also and nothing.

Someone’s been through it?


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, Startservidor became a Thread, which is usually where I write messages in the Jtextarea. When I didn’t have this "Startservidor" as a Thread, it didn’t update the Jtextarea when I called writeTextArea(String msg);

Code of the Startservidor:

  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) {
        }
    }
}

This way, it is writing correctly, however, I do not know if it is the best way, I do not know nor if it is correct to do so. That is why I would like your help. I have looked at the documentation and it says nothing about it.

  • It is possible that you have two Jtextarea in your project, however one has been added to Jframe and the other has not. You could show us your code?

  • @Math When I click on a button, it does the following: writeTextArea("Iniciando servidor..."); Nothing else is here: private void writeTextArea(String msg){
 area.append(msg+"\n");
 };

  • and you’re sure you didn’t instantiate two Jtextarea objects?

  • @Math Tenho. I only have one instance of Jtextarea. The funny thing is that if I give a gextText to show in a Joptionpane for example, it shows all the text.

  • @Math http://www.guj.com.br/java/308638-jtextarea-recebe-o-append-mas-nao-exibe-o-texto-added Here he highlighted better. But I’m in the same trouble.

  • I read the link you passed. Unfortunately there he did not give the solution right? Anyway.. Your code is too big? Because I believe that making it available would make it easier to help you. Maybe if you make one Minimum, Complete and Verifiable Example help as well.

  • 1

    Your text area is inside a JScrollPane such as the linked example? The problem remains if you take it out of there? And your model - Document - is the default? (if you don’t know what I’m talking about then yes, it’s the default) P.S. I agree with Math, put a full example,.

  • By the way, you’re doing heavy processing on Event Dispatcher Thread? (ex.: when you click on a button, the button itself actionPerformed this button starts a loop that takes time to finish) If the answer is yes, then it is explained your problem... See that my answer in another question for more details (the context is different, but the root cause would be the same).

  • @Math I updated the code up there if you can take a look. Thanks.

  • @mgibsonbr I updated the code up there. Before I put "Startservidor" as a Thread, within this class it has basically a while(true) inside it to accept socket connections. Is that why? But why after I implemented Runnable in "Startservidor" did he update Jtexarea correctly? Thanks for the help.

  • @Cristianobombazar Exactly! I will post a reply with more details.

Show 6 more comments

2 answers

4


When I click on a button, it has this call:

Any code executed in response to a button click runs on Event Dispatcher Thread. This thread is used for virtually 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 running the Swing will do nothing else (repaint screens, update components, etc).

In this way, Startservidor became a Thread, which is usually where I write messages in the Jtextarea. When I didn’t have this "Startservidor" as a Thread, it didn’t update the Jtextarea when I called writeTextArea(String msg);

In fact, before you moved your code to a separate thread, the loop that awaited new connections ran on Event Dispatcher Thread. That means that the actionPerformed never returned! He stood still, waiting for the socket connections, and with that Swing did nothing else. When you tried to use setText in Jtextarea, he updated his model (Document) but did not touch the vision. So, if you did:

area.getText();

It would give you 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 (because who updates the screen is the Event Dispatcher Thread, and he’s standing around waiting for his code to finish running).

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

Yes, that way is correct. But the best way would be to use a SwingWorker: a specific thread type for tasks started via Swing. Here a documentation (in English) describing its use and its benefits. But if you want to keep doing it the way it is, you don’t have the slightest problem.

Important detail: 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 must do it by one of the special methods of SwingUtilities. 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
  • Thanks for the answer. I didn’t know this part of Sweingutilities and Swingworker, so I have some questions. As for why he didn’t update Jtexarea, Putz, I explain very well. For example, if I didn’t want to put Startservidor running in a separate Thread, I would put all my code inside Swingutilities.invokeLater() to get the same result?

  • 1

    @Cristianobombazar No, the invokeLater does the opposite: takes a code that would be in any thread and puts it in the Event Dispatcher Thread. If you is already in the EDT, it makes no sense to use this method (and it would do no good either, because it would block in the same way). It has to be a separate thread - or a normal one, which you didn’t do, or a SwingWorker. One way or another it’s OK.

1

Your method code writeTextArea(String msg) could be like this:

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

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

  • Hi. Thanks pro reply. He was already repaint, but it did not work, so I removed. I’m going to post an example that I made very simple, not from my code, but that’s probably going to be the same problem that everyone’s going to face. Sorry if I’m not posting the posts correctly here on the topic, I’m still getting used to the forum.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.