Jswq
Jswq

Reputation: 776

Disable JButton after click and enable when it done it's job

I have a JButton which has an ActionListener, which does its job as many times as I click it. Below is my code:

   mouseListener = new ActionListener() {
        public void actionPerformed(ActionEvent e) {
                JButton source = (JButton) e.getSource();
                source.setEnabled(false);
                try {
                    RequestCommon.ctbCookie = jtf.getText();
                    System.out.println(RequestCommon.ctbCookie);
                    HttpURLConnection connection = HttpURLConnectionBuilder.getConnection(RequestCommon.login, RequestCommon.getCtb888Headers());
                    String connectionOuput = HttpURLConnectionBuilder.getConnectionOuput(connection);
                    System.out.println(connectionOuput);
                    new Player(new BufferedInputStream(new FileInputStream(new File("sounds/8.mp3")))).play();
                } catch (IOException e1) {
                    e1.printStackTrace();
                } catch (JavaLayerException e1) {
                    e1.printStackTrace();
                }
                source.setEnabled(true);
        }
    }
    jb1.addActionListener(mouseListener);

I want it so that no matter how many times I click while the job is running it won't execute again. When the job is done, if I click again, the job will run again. I don't know how to do that, please tell me if you know, thanks!

Upvotes: 1

Views: 4380

Answers (4)

Asen Nikolaev
Asen Nikolaev

Reputation: 11

You should use if and check if the button is enabled before executing your code.

  JButton source = (JButton) e.getSource();
 if(source.isEnabled()) {
                 .
.
. 
execute your code

Upvotes: 0

camickr
camickr

Reputation: 324207

Long running code should NOT execute on the Event Dispatch Thread (EDT). You need to start a separate Thread to do you HTTP request.

The easiest way to do this is to use a SwingWorker. You can disable the button before you start the worker and then the worker has a done() method that is invoked and you can enable the button.

Read the section from the Swing tutorial on Concurrency in Swing for more information about the EDT and a working example of a Swing worker.

Edit:

People seem confused about event handling. The listeners for an event are invoked before the next event is handled. So in the case of "double clicking" on the button. The button is disable on the first click and the long running task is started. The second click is then received on the disable button so the ActionListener is not invoked.

Here is some old code I have lying around which was written before a SwingWorker existed. The basic logic for the "Start in New Thread" button is:

  1. disable the button so it can't be click while processing is happening
  2. simulate a long running task by looping 10 times and sleeping
  3. enable the button so the task can be done again

Here is the code:

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

/*
* A couple of notes about long running tasks and GUI updates:
*
* 1) all GUI painting should be done in the event thread
* 2) GUI painting is not done until the event thread processing is done
*
* This means that long running code (database access, file processing ...)
* should not be done in the event thread. A new thread can be created for
* these tasks.
*
* Most Swing methods are not thread safe. If the long running task needs
* to update the GUI for any reason then the SwingUtilities class
* should be used to add code to the event thread.
*
* See the Swing tutorial on "Using Threads" for more information
* http://java.sun.com/docs/books/tutorial/uiswing/misc/threads.html
*/
public class InvokeLaterTest extends JFrame
    implements ActionListener, Runnable
{
    JLabel status;
    JButton eventThread;
    JButton newThread;
    JButton stop;
    Thread thread;
    int i;
    boolean stopProcessing;

    public InvokeLaterTest()
    {
        status = new JLabel( "Ready to Process:" );
        status.setHorizontalAlignment( JLabel.CENTER );
        getContentPane().add(status, BorderLayout.NORTH);

        eventThread = new JButton( "Start in Event Thread" );
        eventThread.addActionListener( this );
        getContentPane().add(eventThread, BorderLayout.WEST);

        newThread = new JButton( "Start in New Thread" );
        newThread.addActionListener( this );
        getContentPane().add(newThread, BorderLayout.EAST);

        stop = new JButton( "Stop Processing" );
        stop.addActionListener( this );
        getContentPane().add(stop, BorderLayout.SOUTH);
    }

    public void actionPerformed(ActionEvent e)
    {
        //  Code is executing in Event thread so label will not be updated
        //  and the Stop button will not be enabled.

        if (e.getSource() == eventThread)
        {
            stopProcessing = false;
            run();
        }

        //  Code is executing in a new thread so label will be updated

        else if (e.getSource() == newThread)
        {
            stopProcessing = false;
            thread = new Thread( this );
            thread.start();
        }
        else
        {
            stopProcessing = true;
            status.setText("Processing Stopped");
            setButtons( true );
        }
    }

    public void run()
    {
        setButtons( false );

        for (i = 1; i < 10; i++)
        {
            if ( stopProcessing ) return;

            System.out.println("ProcessingFile: " + i);

            // SwingUtilities makes sure code is executed in the event thread.

            SwingUtilities.invokeLater(new Runnable()
            {
                public void run()
                {
                    status.setText("Processing File: " + i);
                    status.paintImmediately(status.getBounds());
                }
            });

            // simulate log running task

            try { Thread.sleep(1000); }
            catch (Exception e) {}
        }

        SwingUtilities.invokeLater(new Runnable()
        {
            public void run()
            {
                status.setText("Finished Processing");
                setButtons( true );
            }
        });
    }

    private void setButtons(boolean value)
    {
        eventThread.setEnabled( value );
        newThread.setEnabled( value );
    }

    public static void main(String[] args)
    {
        JFrame frame = new InvokeLaterTest();
        frame.setDefaultCloseOperation( EXIT_ON_CLOSE );
        frame.pack();
        frame.setLocationRelativeTo( null );
        frame.show();
    }
}

A SwingWorker is similar to the above logic but:

  1. you need to disable the button outside the SwingWorker
  2. the worker will create the Thread for you and execute the code
  3. when the worker is finished the done() method of the worker is invoked so you can enable the button.

Upvotes: 5

Saran
Saran

Reputation: 146

Added a completedTime variable to hold the timestamp as when the action is complete, and every event has the time when it is generated, compare and return if it is less than the completed time

 long completedTime;

    mouseListener = new ActionListener() {
        public void actionPerformed(ActionEvent e) {
                JButton source = (JButton) e.getSource();
                long timeStamp = e.getWhen();

                   if (timeStamp < completedTime) {

                       System.out.println("returned");
                       return;
                   }
               // source.setEnabled(false);
                try {
                    RequestCommon.ctbCookie = jtf.getText();
                    System.out.println( RequestCommon.ctbCookie );
                    HttpURLConnection connection = HttpURLConnectionBuilder.getConnection(RequestCommon.login, RequestCommon.getCtb888Headers());
                    String connectionOuput = HttpURLConnectionBuilder.getConnectionOuput(connection);
                    System.out.println(connectionOuput);
                    new Player(new BufferedInputStream(new FileInputStream(new File("sounds/8.mp3")))).play();
                } catch (IOException e1) {
                    e1.printStackTrace();
                } catch (JavaLayerException e1) {
                    e1.printStackTrace();
                }
               // source.setEnabled(true);
                completedTime = System.currentTimeMillis();
        }
    };

Upvotes: -1

Ben Sch
Ben Sch

Reputation: 104

JButton source = (JButton) e.getSource();

        if (source.isEnabled()) {
            Executors.newSingleThreadScheduledExecutor().execute(() -> {

                    source.setEnabled(false);

                    --your code here--

                    source.setEnabled(true);
                }
            );
        }
    };

Upvotes: -1

Related Questions