Swing - Thread.sleep() stop JTextField.setText() working [duplicate]
When you use Thread.sleep()
you're doing it on the main thread. This freezes the gui for five seconds then it updates the outputField
. When that happens, it uses the last set text which is blank.
It's much better to use Swing Timers and here's an example that does what you're trying to accomplish:
if (match) {
// Another class calculates
} else {
outputField.setText("INPUT ERROR");
ActionListener listener = new ActionListener(){
public void actionPerformed(ActionEvent event){
outputField.setText("");
}
};
Timer timer = new Timer(5000, listener);
timer.setRepeats(false);
timer.start();
}
As Philip Whitehouse states in his answer, you are blocking the swing Event Dispatch Thread with the Thread.sleep(...)
call.
Given that you've taken the time to set up an ActionListener
already, it would probably be easiest to use a javax.swing.Timer
to control clearing the text. To do this, you could add a field to your GUI
class:
private Timer clearTimer = new Timer(5000, this);
In the constructor for GUI
, turn off the repeats feature, as you really only need a one-shot:
public GUI() {
clearTimer.setRepeats(false);
createFrame();
}
Then, actionPerformed
can be modified to use this to start the timer/clear the field:
public void actionPerformed(ActionEvent e) {
if (e.getSource() == equals) {
inputField.setText(inputField.getText().replaceAll("\\s", ""));
String text = inputField.getText();
System.out.println(text);
Pattern equationPattern = Pattern.compile("[\\d(][\\d-+*/()]+[)\\d]");
boolean match = equationPattern.matcher(text).matches();
System.out.println(match);
if (match) {
// Another class calculates
} else {
clearTimer.restart();
outputField.setText("INPUT ERROR"); // This doesn't appear
}
} else if (e.getSource() == clearTimer) {
outputField.setText("");
}
}
You're doing a Thread.sleep()
in the Swing main thread. This is NOT good practice. You need to use a SwingWorker
thread at best.
What's happening is that it's running the first line, hitting Thread.sleep()
.
This prevents the (main) EDT thread from doing any of the repaints (as well as preventing the next line executing).
You should use a javax.swing.Timer
to setup the delayed reaction and not put sleep()
calls in the main thread.