Why is my JTextArea not updating?
I have code as follows:
class SimplifiedClass extends JApplet {
private JTextArea outputText;
/开发者_JAVA百科/ 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?
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
}
});
}
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);
}
}
});
}
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
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);
}
});
}
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);
}
}
}
}
}
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.
精彩评论