In einer Master/Detail-Ansicht habe ich eine Reihe von Textfeldern (und ein oder zwei andere Steuerelemente), die sich alle auf die Details des aktuell ausgewählten Artikels beziehen. Sie haben alle das gleiche DocumentListener
Wenn Sie also eines dieser Elemente ändern, werden zwei Schaltflächen zum Speichern und Verwerfen aktiviert. Die Schaltflächen rufen eine Methode auf und ich kann problemlos Elemente speichern/verwerfen.
Wenn ich jedoch InputMap
y ActionMap
eine gemeinsame saveAction mit der Eingabetaste und eine gemeinsame discardAction mit der Escape-Taste zu verbinden, funktioniert die discardAction nur bei einigen Feldern (saveAction funktioniert bei allen).
Bei der Protokollierung kann ich sehen, dass für die Felder, die funktionieren, zuerst die discardAction ausgelöst wird, gefolgt von der entsprechenden Kombination von removeUpdate und insertUpdate.
Bei den Feldern, die nicht funktionieren, wird die discardAction nie ausgelöst. Genug geplaudert - hier ist der relevante Code (kopieren und einfügen, nicht paraphrasieren):
docChangeListener = new DocumentListener() {
public void insertUpdate(DocumentEvent de) {
System.out.println("\t insertUpdate just got triggered");
memberDetailsChanged(de);
}
public void removeUpdate(DocumentEvent de) {
System.out.println("\t removeUpdate just got triggered");
memberDetailsChanged(de);
}
public void changedUpdate(DocumentEvent de) {
// Not a styled document, safely ignore
}
};
saveAction = new AbstractAction() {
public void actionPerformed(ActionEvent ae) {
System.out.println("\t saveAction just got triggered");
saveChanges();
}
};
discardAction = new AbstractAction() {
public void actionPerformed(ActionEvent ae) {
System.out.println("\t discardAction just got triggered");
discardChanges();
}
};
private void registerDetailField(final JTextField field) {
field.getDocument().putProperty("field", field);
field.getInputMap().put(KeyStroke.getKeyStroke("ENTER"), "saveActionKey");
field.getActionMap().put("saveActionKey", saveAction);
field.getInputMap().put(KeyStroke.getKeyStroke("ESCAPE"), "discardActionKey");
field.getActionMap().put("discardActionKey", discardAction);
field.getDocument().addDocumentListener(docChangeListener);
}
Alle Textfelder werden auf die gleiche Weise registriert (mit registerDetailField()
). Sie haben auch putClientProperty
aufgerufen, um ihnen einen Typ für die Validierung zuzuweisen (siehe unten).
Der EINZIGE Unterschied zwischen den Feldern, die funktionieren, und den Feldern, die nicht funktionieren, ist der eigentliche Validierungsprozess. Ich werde es kürzen, weil es so lang ist, aber ich glaube, ich muss es einschließen. discardAction scheint zuerst für die Felder, die Arbeit, aber die Felder, die nicht funktionieren alle benutzerdefinierte Validierung gemeinsam haben zu feuern.
private void verifyField(final JTextField field) {
int fieldType = ((Integer)field.getClientProperty("type")).intValue();
String fieldValue = field.getText();
switch (fieldType) {
case STANDARD_FIELD:
return; // No validation at the moment
case MEMBER_NUMBER_FIELD:
if (fieldValue.length() == 0) { // Field is required
field.setBackground(REQUIRED_COLOUR);
field.setToolTipText("This is a required field");
invalidFields.add(field);
return;
}
// Check proposed value is valid
if (customTableModel.memberNumStringIsValid(fieldValue,
selectedMember.getMemberNumber())) {
field.setBackground(NORMAL_COLOUR);
field.setToolTipText(null);
invalidFields.remove(field);
} else {
field.setBackground(ERROR_COLOUR);
field.setToolTipText("This value must be a unique,
positive number");
invalidFields.add(field);
}
return;
/* SNIP */
default:
return;
}
}
Hoffentlich ist es ein einfaches Problem mit meiner verifyField-Methode, die ich aufgrund von Schlafmangel übersehe, aber im Moment bin ich völlig ratlos.