Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/redis/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 在后台作业时禁用JButton,以避免多次单击_Java_Swing_Thread Safety_Jbutton - Fatal编程技术网

Java 在后台作业时禁用JButton,以避免多次单击

Java 在后台作业时禁用JButton,以避免多次单击,java,swing,thread-safety,jbutton,Java,Swing,Thread Safety,Jbutton,我需要停止用户在第一次单击仍在执行时多次单击JButton 我能够为这个问题找到一个解决方案,但我不完全理解为什么它会起作用 贝娄,我张贴了代码(修剪到最低限度)的工作和一个不工作 在第一个示例(好)中,如果您运行它并多次单击按钮,则只有一个操作被视为第二个示例(坏),如果您多次单击鼠标,则至少会执行两次操作 第二个(坏)示例根本没有使用invokeLater()方法 行为上的差异从何而来 导入java.awt.event.ActionEvent; 导入java.awt.event.Action

我需要停止用户在第一次单击仍在执行时多次单击JButton

我能够为这个问题找到一个解决方案,但我不完全理解为什么它会起作用

贝娄,我张贴了代码(修剪到最低限度)的工作和一个不工作

在第一个示例(好)中,如果您运行它并多次单击按钮,则只有一个操作被视为第二个示例(坏),如果您多次单击鼠标,则至少会执行两次操作

第二个(坏)示例根本没有使用invokeLater()方法

行为上的差异从何而来

导入java.awt.event.ActionEvent;
导入java.awt.event.ActionListener;
导入java.util.logging.Level;
导入java.util.logging.Logger;
导入javax.swing.*;
公共类TestButtonTask{
公共静态void main(字符串[]args){
最终JFrame=新JFrame(“测试”);
frame.setDefaultCloseOperation(WindowConstants.DISPOSE\u ON\u CLOSE);
最终JButton任务=新JButton(“测试”);
task.addActionListener(新ActionListener(){
@凌驾
已执行的公共无效操作(操作事件e){
long t=System.currentTimeMillis();
System.out.println(“收到的行动”);
task.setText(“工作…”);
task.setEnabled(false);
SwingUtilities.invokeLater(新线程(){
@凌驾
公开募捐{
试一试{
睡眠(2*1000);
}捕获(中断异常例外){
Logger.getLogger(TestButtonTask.class.getName()).log(Level.SEVERE,null,ex);
}
SwingUtilities.invokeLater(新的Runnable(){
公开募捐{
task.setEnabled(true);
task.setText(“测试”);
}
});
}
});
}
});
frame.add(任务);
frame.pack();
frame.setVisible(true);
}//末端总管
}//结束类
现在是“错误”代码

导入java.awt.event.ActionEvent;
导入java.awt.event.ActionListener;
导入java.util.logging.Level;
导入java.util.logging.Logger;
导入javax.swing.*;
公共类TestButtonTask{
公共静态void main(字符串[]args){
最终JFrame=新JFrame(“测试”);
frame.setDefaultCloseOperation(WindowConstants.DISPOSE\u ON\u CLOSE);
最终JButton任务=新JButton(“测试”);
task.addActionListener(新ActionListener(){
@凌驾
已执行的公共无效操作(操作事件e){
long t=System.currentTimeMillis();
System.out.println(“收到的行动”);
task.setText(“工作…”);
task.setEnabled(false);
SwingUtilities.invokeLater(新线程(){
@凌驾
公开募捐{
试一试{
睡眠(2*1000);
}捕获(中断异常例外){
Logger.getLogger(TestButtonTask.class.getName()).log(Level.SEVERE,null,ex);
}
//SwingUtilities.invokeLater(新的Runnable(){
//公开募捐{
task.setEnabled(true);
task.setText(“测试”);
//}
//});
}
});
}
});
frame.add(任务);
frame.pack();
frame.setVisible(true);
}//末端总管
}//结束类
根据@kleopatra和@Boris Pavlović提供的信息,这里是我创建的代码,它似乎运行得相当不错

导入java.awt.event.ActionEvent;
导入java.awt.event.ActionListener;
导入java.beans.PropertyChangeEvent;
导入java.beans.PropertyChangeListener;
导入java.util.logging.Level;
导入java.util.logging.Logger;
导入javax.swing.*;
公共类TestButtonTask{
公共静态void main(字符串[]args){
最终JFrame=新JFrame(“测试”);
frame.setDefaultCloseOperation(WindowConstants.DISPOSE\u ON\u CLOSE);
最终JButton任务=新JButton(“测试”);
task.addActionListener(新ActionListener(){
@凌驾
已执行的公共无效操作(操作事件e){
task.setText(“工作…”);
task.setEnabled(false);
SwingWorker worker=新SwingWorker(){
@凌驾
受保护的Void doInBackground()引发异常{
试一试{
线程。睡眠(3*1000);
}捕获(中断异常例外){
Logger.getLogger(TestButtonTask.class.getName()).log(Level.SEVERE,null,ex);
}
返回null;
}                    
};
worker.addPropertyChangeListener(新的PropertyChangeListener(){
@凌驾
公共作废属性更改(属性更改事件evt){
System.out.println(“事件”+evt+“名称”+evt.getPropertyName()+“值”+evt.getNewValue());
if(“DONE”.equals(evt.getNewValue().toString())){
task.setEnabled(true);
task.setText(“测试”);
}
}
});
worker.execute();
}
});
frame.add(任务);
frame.pack();
    Action taskAction = new AbstractAction("Test") {

        @Override
        public void actionPerformed(ActionEvent e) {
            System.out.println("Action received ");
            setEnabled(false);
            putValue(NAME, "Working...");
            startTask();
        }

        // simulate starting a task - here we simply use a Timer
        // real-world code would spawn a SwingWorker
        private void startTask() {
            ActionListener l = new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    putValue(NAME, "Test");
                    setEnabled(true);

                }
            };
            Timer timer = new Timer(2000, l);
            timer.setRepeats(false);
            timer.start();
        }};

     JButton task = new JButton(taskAction);
public abstract class SingletonSwingWorker extends SwingWorker {

    abstract void initAndGo();

    private static HashMap<Class, SingletonSwingWorker> workers;
    public static void runWorker(SingletonSwingWorker newInstance) {
        if(workers == null) {
            workers = new HashMap<>();
        }
        if(!workers.containsKey(newInstance.getClass()) || workers.get(newInstance.getClass()).isDone()) {
            workers.put(newInstance.getClass(), newInstance);
            newInstance.initAndGo();
        }
    }
}
public static void main(String[] args) {
    final JFrame frame = new JFrame();
    JButton button = new JButton("Click");
    button.setMultiClickThreshhold(5);
    button.addActionListener(new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
            DisplayText_Task.runWorker(new DisplayText_Task(frame));
        }
    });

    JPanel panel = new JPanel();
    panel.add(button);
    frame.add(panel);
    frame.pack();
    frame.setLocationRelativeTo(null);
    frame.setVisible(true);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}

static class DisplayText_Task extends SingletonSwingWorker {

    JFrame dialogOwner;
    public DisplayText_Task(JFrame dialogOwner) {
        this.dialogOwner = dialogOwner;
    }

    JDialog loadingDialog;
    @Override
    void initAndGo() {
        loadingDialog = new JDialog(dialogOwner);
        JProgressBar jpb = new JProgressBar();
        jpb.setIndeterminate(true);
        loadingDialog.add(jpb);
        loadingDialog.pack();
        loadingDialog.setVisible(true);
        execute(); // This must be put in the initAndGo() method or no-workie
    }

    @Override
    protected Object doInBackground() throws Exception {
        for(int i = 0; i < 100; i++) {
            System.out.println(i);
            Thread.sleep(200);
        }
        return null;
    }

    @Override
    protected void done() {
        if(!isCancelled()) {
            try {
                get();
            } catch (ExecutionException | InterruptedException e) {
                loadingDialog.dispose();
                e.printStackTrace();
                return;
            }
            loadingDialog.dispose();
        } else
            loadingDialog.dispose();
    }

}