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