java JOptionPane如何不尊重同步?
我有一个系统,我需要能够问一个简单的“继续?”风格问题。有一个文本字段和一个按钮。要么单独修改文本字段,要么单独按下按钮,我需要能够要求用户确认。因此,我在文本字段上有一个焦点侦听器,在按钮上有一个动作侦听器
但是,如果我编辑该字段,并立即单击该按钮,将弹出两个确认对话框——一个来自焦点侦听器,另一个来自动作侦听器。现在,我显然只需要确认一次,所以我尝试同步抛出JOptionPane的函数,这样就不会输入两次,但似乎没有效果
一些代码演示了这一点:
public class Main extends JFrame {
static public void main(String [] args) {
SwingUtilities.invokeLater(() -> {
Main m = new Main();
m.setVisible(true);
});
}
private JTextField field;
private JButton button;
private boolean isValid;
public Main() {
isValid = false;
setLayout(new BorderLayout());
field = new JTextField(15);
field.addFocusListener(new FocusListener() {
@Override
public void focusGained(FocusEvent arg0) {}
@Override
public void focusLost(FocusEvent e) {
doValidate();
}
});
add(field, BorderLayout.CENTER);
button = new JButton("Push Me");
button.addActionListener((ActionEvent e) -> {
doValidate();
doAction();
});
add(button, BorderLayout.SOUTH);
pack();
}
private synchronized void doValidate() {
System.out.println("Validating");
if(!isValid) {
int answer = JOptionPane.showConfirmDialog(this, "Really do it?");
if(answer == JOptionPane.YES_OPTION)
isValid = true;
}
}
private void doAction() {
System.out.println("Action done!");
}
}
首先,这有点令人惊讶。我希望有人能解释一下Swing/JOptionPane是如何绕过synchronized关键字的
至于如何处理,我的想法是需要实现一个线程,等待确认对话框的答案。然后,我需要检查线程是否处于活动状态(如果对话框已经启动,也就是说),如果它已启动,我需要在给出答案时添加一个侦听器。我已经开始这样做了,但这感觉像是在设计问题的解决方案,特别是因为我对为什么会发生这种情况的理解非常有限。此外,我已经可以想象到至少在一些不同的情况下,我最终会遇到麻烦,这可能会使它更容易出错
==编辑===
需要说明的是,这些消息框是同时弹出的,而不是按顺序弹出的。例如:
# 1 楼答案
Synchronized(同步)意味着两个线程不能同时进入块,永远不能。他们只需等待其他线程释放对该方法的锁定,然后调用它。因此你有两个对话
这可能与此无关,因为我认为UI呈现是同一个线程,所以您只需从两个单独的UI事件中调用同一个方法两次(这一点我可能错了)
至于如何让它工作,不要担心线程,而是查看
DocumentListener
# 2 楼答案
我建议添加以下内容,以便单击红色的x将退出程序
请考虑只需删除按钮侦听器即可得到想要的行为。以下是我认为可以让您实现所需行为的代码: