Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

make button unresponsive for a while java [duplicate]

Tags:

java

swing

I was trying a simple code in java for test, just a button when u click it it sleeps for 5 seconds, here's the handler

private void jButton1ActionPerformed(java.awt.event.ActionEvent evt)    {                                               
    try {
        System.out.println ("hiiii");
        Thread.sleep (5000);
        System.out.println ("bye");        
    } catch (InterruptedException ex) {
        Logger.getLogger(NewJFrame.class.getName()).log(Level.SEVERE, null, ex);
    }
} 

I want this button doesn't receive any events until it finishes working (5 seconds), I tried to disable and enable it in the handler but in vain

private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {                                         

    jButton1.setEnabled(false);

    try {
        System.out.println ("hiiii");
        Thread.sleep (5000);
        System.out.println ("bye");        
    } catch (InterruptedException ex) {
        Logger.getLogger(NewJFrame.class.getName()).log(Level.SEVERE, null, ex);
    }

    jButton1.setEnabled(true);
} 
like image 501
Mohamed Yacout Avatar asked Jul 25 '26 11:07

Mohamed Yacout


1 Answers

You have to move any long-running task (in your case it is a simple sleep call) outside the EDT (Event Dispatch Thread) - that thread is used to render UI, if you block it with some operation - you block all your UI at once.

Here is a proper example how you can disable/enable button:

import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

/**
 * @author Mikle Garin
 * @see http://stackoverflow.com/a/18590057/909085
 */

public class ButtonSleep
{
    public static void main ( String[] args )
    {
        JFrame frame = new JFrame ( "Custom list renderer" );

        final JButton button = new JButton ( "Make me sleep 5 seconds" );
        button.addActionListener ( new ActionListener ()
        {
            @Override
            public void actionPerformed ( ActionEvent e )
            {
                button.setEnabled ( false );
                new Thread ( new Runnable ()
                {
                    @Override
                    public void run ()
                    {
                        try
                        {
                            Thread.sleep ( 5000 );
                        }
                        catch ( InterruptedException e1 )
                        {
                            //
                        }
                        SwingUtilities.invokeLater ( new Runnable ()
                        {
                            @Override
                            public void run ()
                            {
                                button.setEnabled ( true );
                            }
                        } );
                    }
                } ).start ();
            }
        } );
        frame.add ( button );

        frame.pack ();
        frame.setLocationRelativeTo ( null );
        frame.setDefaultCloseOperation ( JFrame.EXIT_ON_CLOSE );
        frame.setVisible ( true );
    }
}

Yes, it seems weird, but you have to move your operations to a separate thread (doesn't really matter which thread) and you have to execute any operations with UI (in this case - enabling/disabling button) inside the EDT - that is why i call setEnabled in invokeLater call and not inside the separate thread.

And yes, all Swing component listeners event calls are executed inside EDT from the beginning, so you are already inside EDT when you start executing your code inside actionPerformed method of your action listener - that is why you block the whole UI if you call sleep there.

like image 132
Mikle Garin Avatar answered Jul 28 '26 14:07

Mikle Garin



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!