[Swing] Limiter la saisie dans une combobox editable

Plus compliqué qu'il n'y parait!

Le composant qui permet de saisir du texte dans ce type de combobox est un simple JTextField, mais il est impossible de paramétrer son nombre de caractères maximal aussi simplement qu'avec un JTextField classique.

Le text field est accessible grâce au code suivant :

JTextField tf = (JTextField)(combo.getEditor().getEditorComponent());

La solution consiste donc à modifier l'objet Document associé au champ (ici la limite sera fixée à 32 caractères) :

tf.setDocument(new JTextFieldLimit(32));

class JTextFieldLimit extends PlainDocument {
    private int limit;
    JTextFieldLimit(int limit) {
        super();
        this.limit = limit;
    }
    @Override
    public void insertString(int offset, String str, AttributeSet attr) {
        try {
            if (str == null)
                return;
            if ((getLength() + str.length()) <= limit) {
                super.insertString(offset, str, attr);
             }
        } catch (BadLocationException e) {}
    }
}

Un problème persiste cependant : à chaque fois que l'utilisateur essaiera de taper plus de 32 caractères, une erreur sera levée dans la console :

Exception in thread "AWT-EventQueue-0" java.lang.IllegalArgumentException: bad position: 33
        at javax.swing.text.JTextComponent.moveCaretPosition(JTextComponent.java:1523)
        at org.jdesktop.swingx.autocomplete.AbstractAutoCompleteAdaptor.markText(AbstractAutoCompleteAdaptor.java:116)
        at org.jdesktop.swingx.autocomplete.AutoCompleteDocument.insertString(AutoCompleteDocument.java:161)
        at javax.swing.text.JTextComponent.replaceSelection(JTextComponent.java:1358)
...

Cette erreur est volontairement levée par le composant java afin de maximiser la rétro-compatibilité, comme justifié dans ce bug : Oracle bug database (4903033). Il faut donc s'en contenter ou arriver à encapsuler suffisamment le composant pour récupérer l'erreur.


Fichier(s) joint(s) :

0 commentaires: