4

I have a button doing a long function, I want to disable this button after the user once click on it to in order to prevent him from clicking it again many times

The button gets disabled but the problem is after the function finished the button gets enabled again
i tried to put button.setEnabled(false); in a new thread but it didn't work either

for testing this sample of code

button.addActionListener(new ActionListener() {
    @Override
    public void actionPerformed(ActionEvent ae) {
        button.setEnabled(false);
        for (int i = 0; i < Integer.MAX_VALUE; i++) {
            for (int j = 0; j < Integer.MAX_VALUE; j++) {
                for (int ii = 0; ii < Integer.MAX_VALUE; ii++) {
                }
            }
        }
    }
});
Cœur
  • 37,241
  • 25
  • 195
  • 267
Steve
  • 503
  • 3
  • 9
  • 19
  • why don't you put "button.enabled(false)" to end of for loops, Please can you clear which function finish. – user217895 Jul 23 '13 at 10:45
  • 1
    Don't block the EDT (Event Dispatch Thread) - the GUI will 'freeze' when that happens. Instead of calling `Thread.sleep(n)` implement a Swing `Timer` for repeating tasks or a `SwingWorker` for long running tasks. See [Concurrency in Swing](http://docs.oracle.com/javase/tutorial/uiswing/concurrency/) for more details. – Andrew Thompson Jul 23 '13 at 10:46
  • @user217895 Because a) that is not the problem, and b) it would defeat the purpose of what the OP is trying to achieve! – Andrew Thompson Jul 23 '13 at 10:46
  • @user217895 `button.enabled(false)` dose not exist in java – Steve Jul 23 '13 at 10:48
  • _The button gets disabled but the problem is after the function finished the button gets enabled again_ I tried running your code. The problem I encountered is the UI freezes. The button is still disabled after the function is executed contrary to your findings. Perhaps you missed some codes that causes the reenabling of the button? – Bnrdo Jul 23 '13 at 10:59

3 Answers3

6

Use SwingWorker for long running background tasks. In this example, the startButton action does setEnabled(false), and the worker's done() implementation does setEnabled(true).

Community
  • 1
  • 1
trashgod
  • 203,806
  • 29
  • 246
  • 1,045
2
  • everything wrapped in public void actionPerformed(ActionEvent ae) { is done at one moment, (on the screen) when all code lines are executed, this is basic rule for AWT/Swing Listeners and EventDispatchThread

  • you need to delay event in EDT by using

    1. short delay with Swing Timer,
    2. redirect rest of code (after button.setEnabled(false);) to SwingWorker, easiest to Runnable#Thread, note all output from Runnable#Thread to the already visible Swing GUI must be wrapped into invokeLater
  • proper of ways will be only using Swing Action and instead of locking the JButton to set Action.setEnabled(false) only

mKorbel
  • 109,525
  • 20
  • 134
  • 319
1

Edit: It's tempting to think you could use a mouse listener to implement this. For example, to prevent you could use mouse released event or mouse clicked event of mouse listener. Inside that you could write button.setEnable(false). Unfortunately, this also blocks the event dispatch thread.

trashgod
  • 203,806
  • 29
  • 246
  • 1,045
Nirav Kamani
  • 3,192
  • 7
  • 39
  • 68
  • 2
    *"try it..."* Try puting an upper case letter at the start of sentences, to make the message easier to read. *"it will work..."* It will fail even worse than what the code is currently doing, especially when the user navigates to the button and presses 'Enter' (i.e. no `MouseEvent` will be fired at all). – Andrew Thompson Jul 23 '13 at 11:03
  • 1
    Blocking the EDT is not the solution to blocking the EDT. – trashgod Jul 23 '13 at 14:21
  • not the best answer because it not working completely it disabled the button only in view but if you clicked it working because MousePressed,MouseReleased,MouseClicked working always either if the button disabled – Steve Jul 23 '13 at 18:07