2

I need to disable a JButton on on click and enable it again 2 seconds later, so for I've tried sleeping the ui thread from the event handler, but that leaves the button in a selected state where you can't read the text of the disabled button.

The code looks something like this:

JButton button = new JButton("Press me");
button.addActionListener(new ActionListener{
    public void actionPerformed(ActionEvent ae) {
        JButton button = ((JButton)e.getSource());
        button.setEnabled(false);
        button.setText("Wait a second")
        button.repaint();
        try {
           Thread.sleep(2000);
        } catch (InterruptedException ie) {
        }
        button.setEnabled(true);
        button.setText("");
    }

What happens is the button remains in a "being selected" state with no text for the 2 seconds and instantly disables and re-enables the button at the end, which isn't what I want, what I'm aiming for is the button to stay in a disabled state with text on it for two seconds and then re-enable.

What do I do?

Faceplanted
  • 61
  • 3
  • 7
  • 3
    Don't use Thread.sleep on the UI thread (the UI "freezes" and *does not have a chance to repaint*). Use a Timer. There are many duplicates. – user2864740 Apr 02 '15 at 16:24
  • Did you try disabling any button that had text in it outside of any event or timer code to confirm that it produces the effect you want under any circumstances? – clearlight Apr 02 '15 at 16:24
  • 1
    http://stackoverflow.com/questions/4348962/thread-sleep-and-repainting , http://stackoverflow.com/questions/18164944/actionlistener-and-thread-sleep , http://stackoverflow.com/questions/14074329/using-sleep-for-a-single-thread , http://stackoverflow.com/questions/21652914/thread-sleep-stopping-my-paint – user2864740 Apr 02 '15 at 16:25

1 Answers1

5

As user2864740 indicated - "Don't use Thread.sleep on the UI thread (the UI "freezes" and does not have a chance to repaint). Use a Timer class."

Here's an example of the kind of thing he was referring to. Should be close to what you want to do:

JButton button = new JButton("Press me");
int delay = 2000; //milliseconds
Timer timer = new Timer(delay, new ActionListener() {
    public void actionPerformed(ActionEvent evt) {
        button.setEnabled(true);
        button.setText("");
    }
});
timer.setRepeats(false);
button.addActionListener(new ActionListener {
    public void actionPerformed(ActionEvent ae) {
        JButton button = ((JButton)e.getSource());
        button.setEnabled(false);
        button.setText("Wait a second")
        timer.start();
    }
}
Community
  • 1
  • 1
clearlight
  • 12,255
  • 11
  • 57
  • 75
  • @Faceplanted read the javadoc of javax.swing.Timer. In the actionPerformed method, disble the button, and start a timer that will reenable it 1 second later. – JB Nizet Apr 02 '15 at 16:29
  • On stack exchange meta there was a discussion and the consensus was to plagiarize comments and put them into answers. I'm not kidding. But sure, I'll cobble together an example. – clearlight Apr 02 '15 at 16:30
  • 1
    @user2864740 thanks for your input. I did some legwork to make the answer more complete. – clearlight Apr 02 '15 at 16:37
  • @1sand0s Thanks, that is better. I really am flattered that my comment was used at the start (don't need to link me!) but I don't like too-short answers! A reference or two - JB Nizet has a good suggestion - would help round out the details. – user2864740 Apr 02 '15 at 16:40
  • @user2864740 I'm not totally sure what he means but if someone edits it in, I'll accept the changes. – clearlight Apr 02 '15 at 16:46
  • @1sand0s You must start the Timer. Not just construct it. And you must make sure it doesn't execute every 2 seconds, ad vitam aeternam. And button.repain() is useless. – JB Nizet Apr 02 '15 at 17:00
  • @JBNizet Yup. OK did it. Should be close now? – clearlight Apr 02 '15 at 23:22