Ich habe ein System, in dem ich in der Lage sein muss, ein einfaches "weiter?" Stilfrage. Es gibt ein Textfeld und eine Schaltfläche. Ändere entweder das Textfeld isoliert oder drücke den Knopf isoliert und ich muss einen Benutzer zur Bestätigung auffordern können. Das gibt mir einen Fokus-Listener auf das Textfeld und einen Aktions-Listener auf der Schaltfläche.Wie wird JOptionPane nicht synchronisiert?
Wenn ich jedoch das Feld bearbeite und sofort auf die Schaltfläche klicke, erscheinen zwei Bestätigungsdialoge - der aus dem Fokus-Listener und dann der aus dem Aktions-Listener unmittelbar danach. Jetzt brauche ich natürlich nur noch eine Bestätigung, also habe ich versucht, die Funktion zu synchronisieren, die den JOptionPane auslöst, so dass er nicht zweimal eingegeben wird, aber das scheint keine Wirkung zu haben.
Einige Code dies demonstrieren:
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!");
}
}
Zunächst einmal, diese etwas überraschende Verhalten ist. Ich würde mich freuen, wenn jemand eine Erklärung dafür hätte, wie Swing/JOptionPane in der Lage ist, das synchronisierte Keyword zu umgehen.
Wie zu behandeln, ist mein Denken, dass ich einen Thread implementieren muss, der auf die Antwort auf den Bestätigungsdialog wartet. Dann muss ich überprüfen, ob der Thread aktiv ist oder nicht (wenn das Dialogfeld bereits aktiv ist), und wenn es abgelaufen ist, muss ich einen Listener hinzufügen, wenn die Antwort gegeben wird. Ich wäre bereits vorangegangen und hätte dies getan, aber es fühlt sich an, als würde ich eine Lösung für das Problem übersteuern, zumal ich so wenig Verständnis dafür habe, warum dies überhaupt geschieht. Außerdem kann ich mir schon einige Fälle vorstellen, in denen ich in Schwierigkeiten geraten würde, was es wahrscheinlich fehleranfälliger macht.
=== === EDIT
klar sein, pop diese Meldungsfelder in der gleichen Zeit auf, nicht in Folge. Zum Beispiel:
Also, was verwirrend ist, dass JOptionPane.showConfirmDialog() soll eine Sperrfunktion. Die Dialoge erscheinen nicht nacheinander (das wäre sinnvoll), sie öffnen sich parallel! Wenn Sie den Code ausprobieren, sehen Sie, dass die Meldung "Validieren" zweimal erscheint, bevor Sie eine beliebige Taste drücken. –