我需要停止用户在JButton上多次单击,而第一次单击仍在执行。

我能够提供针对此问题的解决方案,但我不完全理解它为什么起作用。

在下面,我发布了行得通的代码(最小化了)。

在第一个示例(好的)中,如果您运行它并多次单击按钮,则仅考虑一个 Action ;对于第二个示例(坏的),如果您多次单击鼠标,则至少要执行两次 Action 。

第二个(不好的)示例根本不使用invokeLater()方法。

行为差异来自何处?

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.*;

public class TestButtonTask {

    public static void main(String[] args) {

        final JFrame frame = new JFrame("Test");
        frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);

        final JButton task = new JButton("Test");

        task.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                long t = System.currentTimeMillis();
                System.out.println("Action received");

                task.setText("Working...");
                task.setEnabled(false);

                SwingUtilities.invokeLater(new Thread() {

                    @Override
                    public void run() {
                        try {
                            sleep(2 * 1000);
                        } catch (InterruptedException ex) {
                            Logger.getLogger(TestButtonTask.class.getName()).log(Level.SEVERE, null, ex);
                        }

                        SwingUtilities.invokeLater(new Runnable() {

                            public void run() {
                                task.setEnabled(true);
                                task.setText("Test");
                            }
                        });

                    }
                });
            }
        });

        frame.add(task);
        frame.pack();
        frame.setVisible(true);
    } //end main
} //end class

现在是“错误的”代码

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.*;

public class TestButtonTask {

    public static void main(String[] args) {

        final JFrame frame = new JFrame("Test");
        frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);

        final JButton task = new JButton("Test");

        task.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                long t = System.currentTimeMillis();
                System.out.println("Action received");

                task.setText("Working...");
                task.setEnabled(false);

                SwingUtilities.invokeLater(new Thread() {

                    @Override
                    public void run() {
                        try {
                            sleep(2 * 1000);
                        } catch (InterruptedException ex) {
                            Logger.getLogger(TestButtonTask.class.getName()).log(Level.SEVERE, null, ex);
                        }

                        //SwingUtilities.invokeLater(new Runnable() {

                            //public void run() {
                                task.setEnabled(true);
                                task.setText("Test");
                            //}
                        //});

                    }
                });
            }
        });

        frame.add(task);
        frame.pack();
        frame.setVisible(true);
    } //end main
} //end class

在@kleopatra和@BorisPavlović提供的信息之后,这是我创建的代码,看起来似乎不错。

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.*;

public class TestButtonTask {

    public static void main(String[] args) {

        final JFrame frame = new JFrame("Test");
        frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);

        final JButton task = new JButton("Test");

        task.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                task.setText("Working...");
                task.setEnabled(false);

                SwingWorker worker = new SwingWorker<Void, Void>() {

                    @Override
                    protected Void doInBackground() throws Exception {
                        try {
                            Thread.sleep(3 * 1000);
                        } catch (InterruptedException ex) {
                            Logger.getLogger(TestButtonTask.class.getName()).log(Level.SEVERE, null, ex);
                        }

                        return null;
                    }
                };

                worker.addPropertyChangeListener(new PropertyChangeListener() {
                    @Override
                    public void propertyChange(PropertyChangeEvent evt) {
                        System.out.println("Event " + evt + " name" + evt.getPropertyName() + " value " + evt.getNewValue());
                        if ("DONE".equals(evt.getNewValue().toString())) {
                            task.setEnabled(true);
                            task.setText("Test");
                        }
                    }
                });

                worker.execute();
            }
        });

        frame.add(task);
        frame.pack();
        frame.setVisible(true);
    } //end main
} //end class

最佳答案

你有两个选择

1)JButton#setMultiClickThreshhold

2)您必须将此想法拆分为actionListener或Action内部的两个单独的 Action

  • 1日。步骤JButton#setEnabeld(false);
  • 2nd。步骤,然后调用包装到javax.swing.Action(由javax.swing.Timer并由SwingWorker处理),Runnable#Thread或ojit_code的其余代码
  • 关于java - 禁用JButton,同时执行后台作业,以避免多次单击,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/8428841/

    10-09 13:44