3 Stimmen

Java AbstractAction erkennt manchmal die Escape-Taste nicht - bizarres Verhalten

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.

1voto

akf Punkte 37387

Das Problem, das Sie haben, hängt mit der Einstellung des Tooltip-Textes zusammen. Sobald Sie dies tun, wird die ToolTipManager ersetzt Ihren Schlüssel für die Verwerfungsaktion in der inputMap durch seine eigene hideTip Tastendruck, auch VK_ESCAE.

0voto

Eugene Ryzhikov Punkte 16656

Ich würde vorschlagen, den einzelnen Textfeldern KEINE Aktionen zuzuordnen. Fügen Sie sie an den übergeordneten Container und beim Abrufen von Input-Map von ihm - verwenden WHEN_ANCESTOR_OF_FOCUSED_COMPONENT Bedingung.

Auf diese Weise sind immer dann, wenn dieser Container im Fokus ist, Aktionen verfügbar

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X