J'ai un JButton qui a un actionListener, quand je clique dessus plusieurs fois, il fera son travail autant de fois que je clique, voici mon 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);

Je veux que peu importe combien de fois je clique pendant l'exécution du travail, il ne s'exécutera pas à nouveau. Lorsque le travail est terminé, si je clique à nouveau, le travail sera exécuté à nouveau.Je ne sais pas comment faire, s'il vous plaît dites-moi si vous savez, merci!

1
Jaycee 20 nov. 2017 à 18:55

4 réponses

Meilleure réponse

Le code de longue durée ne doit PAS s'exécuter sur le thread de répartition des événements (EDT). Vous devez démarrer un thread séparé pour faire votre requête HTTP.

La manière la plus simple de procéder est d'utiliser un SwingWorker. Vous pouvez désactiver le bouton avant de démarrer le worker, puis le worker a une méthode done() qui est appelée et vous pouvez activer le bouton.

Lisez la section du tutoriel Swing sur Concurrence dans Swing pour plus d'informations sur l'EDT et un exemple de travail d'un ouvrier Swing.

Éditer:

Les gens semblent confus au sujet de la gestion des événements. Les écouteurs d'un événement sont appelés avant que l'événement suivant ne soit géré. Donc dans le cas d'un "double clic" sur le bouton. Le bouton est désactivé au premier clic et la tâche de longue durée est lancée. Le deuxième clic est ensuite reçu sur le bouton de désactivation afin que l'ActionListener ne soit pas appelé.

Voici un vieux code que j'ai traîner et qui a été écrit avant qu'un SwingWorker n'existe. La logique de base du bouton "Démarrer dans un nouveau fil" est la suivante:

  1. désactiver le bouton pour qu'il ne puisse pas être cliqué pendant le traitement
  2. simuler une tâche de longue durée en bouclant 10 fois et en dormant
  3. activer le bouton pour que la tâche puisse être répétée

Voici le 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();
    }
}

Un SwingWorker est similaire à la logique ci-dessus mais:

  1. vous devez désactiver le bouton en dehors du SwingWorker
  2. le travailleur créera le thread pour vous et exécutera le code
  3. lorsque le worker a terminé, la méthode done() du worker est appelée afin que vous puissiez activer le bouton.
5
camickr 20 nov. 2017 à 17:14
JButton source = (JButton) e.getSource();

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

                    source.setEnabled(false);

                    --your code here--

                    source.setEnabled(true);
                }
            );
        }
    };
-1
Ben Sch 20 nov. 2017 à 16:20

Ajout d'une variable completedTime pour contenir l'horodatage comme lorsque l'action est terminée, et chaque événement a l'heure à laquelle il est généré, comparer et renvoyer s'il est inférieur au temps terminé

 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();
        }
    };
-1
Saran 20 nov. 2017 à 16:22

Je pense que vous devriez utiliser if et vérifier si le bouton est activé avant d'exécuter votre code.

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

J'espère que je vous aide. :)

0
Asen Nikolaev 20 nov. 2017 à 16:01
47396026