Why is my JTextArea not updating?
Asked Answered
U

6

6

I have code as follows:

class SimplifiedClass extends JApplet {

    private JTextArea outputText;
    // Lots of methods
    public void DoEverything() {
        String output = "";
        for(int i = 0; i <= 10; i++) {
            output += TaskObject.someLongTask(i);
            outputText.setText(output);
        }
    }
}

However, instead of updating the text area after each iteration of the loop when setText is called, it appears to only update the text when all the runs of the task are done. Why does this happen, and how can I resolve it?

Undercarriage answered 21/7, 2011 at 10:7 Comment(0)
J
2

You're probably using the Swing thread which is waiting for your code to execute before it can update the UI. Try using a separate thread for that loop.

public void DoEverything() {
  SwingUtilities.invokeLater(new Runnable() {
    public void run() {
      String output = "";
      for(int i = 0; i <= 10; i++) {
        output += TaskObject.someLongTask(i);
        outputText.setText(output);
      }
    }
  });
}
Jog answered 21/7, 2011 at 10:11 Comment(1)
-1 How is this code snippet a separate Thread for the loop. Now you are making sure it is executed on the EDTLacerate
C
4
private JTextArea outputText = new JTextArea();

public void DoEverything() {
    String output = "";
    for(int i = 0; i <= 10; i++) {
        output += TaskObject.someLongTask(i);
        appendNewText(output);
    }
}

public void appendNewText(String txt) {
  SwingUtilities.invokeLater(new Runnable() {
     public void run() {
        outputText.setText(outputText.getText + txt);
       //outputText.setText(outputText.getText + "\n"+ txt); Windows LineSeparator
     }
  });
}
Crossly answered 21/7, 2011 at 10:22 Comment(2)
+1 for continuation.Panlogism
you might want to clarify that the doEverything method must be running a thread other than the EDT :-)Tankage
J
2

You're probably using the Swing thread which is waiting for your code to execute before it can update the UI. Try using a separate thread for that loop.

public void DoEverything() {
  SwingUtilities.invokeLater(new Runnable() {
    public void run() {
      String output = "";
      for(int i = 0; i <= 10; i++) {
        output += TaskObject.someLongTask(i);
        outputText.setText(output);
      }
    }
  });
}
Jog answered 21/7, 2011 at 10:11 Comment(1)
-1 How is this code snippet a separate Thread for the loop. Now you are making sure it is executed on the EDTLacerate
P
2

You are using swing basic threads called initial threads. Use worker threads instead. Try using SwingWorker for worker threads.

For further details, go through the following link: http://docs.oracle.com/javase/tutorial/uiswing/concurrency/index.html

Phenformin answered 24/9, 2012 at 6:55 Comment(0)
B
1

As the post said it is important not to block the EDT (the Event Dispatch Thread). In my exmaple below the actual work starts from the EDT thread as it is from a button click ActionListener. I need to wrap it with a separate thread so it is separated from the Event Dispatch Thread. Thus the EDT is not blocked.

Also note you need to SwingUtilities.invokeLater() when update the UI from a separate Thread. The code example below is simplified a little from my original code. I am actually performing multiple tasks in parallel using multiple threads and in each of those thread the updateProgress() is called to update the TextArea by appending the latest status.

Full source code is here: https://github.com/mhisoft/rdpro/blob/master/src/main/java/org/mhisoft/rdpro/ui/ReproMainForm.java

btnOk.addActionListener(new ActionListener() {
  @Override
  public void actionPerformed(ActionEvent e) {
    //Don't block the EDT, wrap it in a seperate thread
    DoItJobThread t = new DoItJobThread();
    t.start();

  } 
});


class DoItJobThread extends Thread {
    @Override
    public void run() {
       //do some task 
       // output the progress
       updateProgress();    
    }
}


public void updateProgress(final String msg) {
    //invokeLater()
    //This method allows us to post a "job" to Swing, which it will then run
    // on the event dispatch thread at its next convenience.

    SwingUtilities.invokeLater(new Runnable() {
        public void run() {
            // Here, we can safely update the GUI
            // because we'll be called from the
            // event dispatch thread
            outputTextArea.append(msg);
            outputTextArea.setCaretPosition(outputTextArea.getDocument().getLength());
            //labelStatus.setText(msg);
        }
    });

}
Braxy answered 27/11, 2014 at 4:53 Comment(0)
A
0

Run the body of DoEverything() in its own thread:

class SimplifiedClass extends JApplet {

    private JTextArea outputText;
    // Lots of methods
    public void DoEverything() {
        Thread thread = new Thread(new Runnable() {
            public void run() {
                String output = "";
                for(int i = 0; i <= 10; i++) {
                    output += TaskObject.someLongTask(i);
                    outputText.setText(output);
                }
            }
        }
    }
}
Ampulla answered 4/6, 2021 at 6:1 Comment(0)
E
-1

Try using outputText.validate() after outputText.setText(output)

I tried this for my program too which is similar. For some reason using the Thread.sleep(delay) directly following a outputText.setText("dsfgsdfg"), even with a outputText.validate() does not allow the user to see the output. It's the strangest thing. It is as if the code is read after the setText method is trying to be invoked. Then hits the sleep method and it all goes to hell.

Eonian answered 17/5, 2012 at 23:53 Comment(1)
hmm .. this isn't an answer, is it :-)Tankage

© 2022 - 2024 — McMap. All rights reserved.