IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

 Java Discussion :

CellEditor de Double pour une JTable


Sujet :

Java

  1. #1
    Membre confirmé
    Inscrit en
    Juin 2007
    Messages
    68
    Détails du profil
    Informations forums :
    Inscription : Juin 2007
    Messages : 68
    Par défaut CellEditor de Double pour une JTable
    Bonjour,

    Je dispose d'une JTable dont l'une des colonnes ne doit comporter que des doubles positifs. Il faut donc tester l'input utilisateur. Pour ce faire, j'utilise un DefaultCellEditor en me basant sur l'exemple de Sun : IntegerEditor qui décrit le comportement que je souhaite mais pour des entiers:

    En premier voici la source IntegerEditor :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    import javax.swing.AbstractAction;
    import javax.swing.DefaultCellEditor;
    import javax.swing.JFormattedTextField;
    import javax.swing.JOptionPane;
    import javax.swing.JTable;
    import javax.swing.JTextField;
    import javax.swing.KeyStroke;
    import javax.swing.SwingUtilities;
    import java.awt.event.ActionEvent;
    import java.awt.event.KeyEvent;
    import java.awt.Component;
    import java.awt.Toolkit;
    import java.text.NumberFormat;
    import java.text.ParseException;
    import javax.swing.text.DefaultFormatterFactory;
    import javax.swing.text.NumberFormatter;
     
    /**
     * Implements a cell editor that uses a formatted text field
     * to edit Integer values.
     */
    public class IntegerEditor extends DefaultCellEditor {
        JFormattedTextField ftf;
        NumberFormat integerFormat;
        private Integer minimum, maximum;
        private boolean DEBUG = false;
     
        public IntegerEditor(int min, int max) {
            super(new JFormattedTextField());
            ftf = (JFormattedTextField)getComponent();
            minimum = new Integer(min);
            maximum = new Integer(max);
     
            //Set up the editor for the integer cells.
            integerFormat = NumberFormat.getIntegerInstance();
            NumberFormatter intFormatter = new NumberFormatter(integerFormat);
            intFormatter.setFormat(integerFormat);
            intFormatter.setMinimum(minimum);
            intFormatter.setMaximum(maximum);
     
            ftf.setFormatterFactory(
                    new DefaultFormatterFactory(intFormatter));
            ftf.setValue(minimum);
            ftf.setHorizontalAlignment(JTextField.TRAILING);
            ftf.setFocusLostBehavior(JFormattedTextField.PERSIST);
     
            //React when the user presses Enter while the editor is
            //active.  (Tab is handled as specified by
            //JFormattedTextField's focusLostBehavior property.)
            ftf.getInputMap().put(KeyStroke.getKeyStroke(
                                            KeyEvent.VK_ENTER, 0),
                                            "check");
            ftf.getActionMap().put("check", new AbstractAction() {
                public void actionPerformed(ActionEvent e) {
    		if (!ftf.isEditValid()) { //The text is invalid.
                        if (userSaysRevert()) { //reverted
    		        ftf.postActionEvent(); //inform the editor
    		    }
                    } else try {              //The text is valid,
                        ftf.commitEdit();     //so use it.
                        ftf.postActionEvent(); //stop editing
                    } catch (java.text.ParseException exc) { }
                }
            });
        }
     
        //Override to invoke setValue on the formatted text field.
        public Component getTableCellEditorComponent(JTable table,
                Object value, boolean isSelected,
                int row, int column) {
            JFormattedTextField ftf =
                (JFormattedTextField)super.getTableCellEditorComponent(
                    table, value, isSelected, row, column);
            ftf.setValue(value);
            return ftf;
        }
     
        //Override to ensure that the value remains an Integer.
        public Object getCellEditorValue() {
            JFormattedTextField ftf = (JFormattedTextField)getComponent();
            Object o = ftf.getValue();
            if (o instanceof Integer) {
                return o;
            } else if (o instanceof Number) {
                return new Integer(((Number)o).intValue());
            } else {
                if (DEBUG) {
                    System.out.println("getCellEditorValue: o isn't a Number");
                }
                try {
                    return integerFormat.parseObject(o.toString());
                } catch (ParseException exc) {
                    System.err.println("getCellEditorValue: can't parse o: " + o);
                    return null;
                }
            }
        }
     
        //Override to check whether the edit is valid,
        //setting the value if it is and complaining if
        //it isn't.  If it's OK for the editor to go
        //away, we need to invoke the superclass's version 
        //of this method so that everything gets cleaned up.
        public boolean stopCellEditing() {
            JFormattedTextField ftf = (JFormattedTextField)getComponent();
            if (ftf.isEditValid()) {
                try {
                    ftf.commitEdit();
                } catch (java.text.ParseException exc) { }
     
            } else { //text is invalid
                if (!userSaysRevert()) { //user wants to edit
    	        return false; //don't let the editor go away
    	    } 
            }
            return super.stopCellEditing();
        }
     
        /** 
         * Lets the user know that the text they entered is 
         * bad. Returns true if the user elects to revert to
         * the last good value.  Otherwise, returns false, 
         * indicating that the user wants to continue editing.
         */
        protected boolean userSaysRevert() {
            Toolkit.getDefaultToolkit().beep();
            ftf.selectAll();
            Object[] options = {"Edit",
                                "Revert"};
            int answer = JOptionPane.showOptionDialog(
                SwingUtilities.getWindowAncestor(ftf),
                "The value must be an integer between "
                + minimum + " and "
                + maximum + ".\n"
                + "You can either continue editing "
                + "or revert to the last valid value.",
                "Invalid Text Entered",
                JOptionPane.YES_NO_OPTION,
                JOptionPane.ERROR_MESSAGE,
                null,
                options,
                options[1]);
     
            if (answer == 1) { //Revert!
                ftf.setValue(ftf.getValue());
    	    return true;
            }
    	return false;
        }
    }
    Et cette meme source modifiée pour filtrer les doubles. Mon problème étant que meme avec le remplacement de Integer en Double, cette source modifiée continue de n'accepter que les Integer. Pourquoi? Et si possible comment y remedier. Merci.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    public class DoubleEditor extends DefaultCellEditor {
        JFormattedTextField ftf;
        //NumberFormat integerFormat;
        DecimalFormat integerFormat;
        private Double minimum, maximum;
        private boolean DEBUG = false;
     
        public  DoubleEditor(double min, double max) {
            super(new JFormattedTextField());
            ftf = (JFormattedTextField)getComponent();
            minimum = new Double(0.0);
            //maximum = new Integer(max);
     
            //Set up the editor for the integer cells.
            //integerFormat = NumberFormat.getIntegerInstance();
            integerFormat = (DecimalFormat)NumberFormat.getInstance();
            NumberFormatter intFormatter = new NumberFormatter(integerFormat);
            intFormatter.setFormat(integerFormat);
            intFormatter.setMinimum(minimum);
            //intFormatter.setMaximum(maximum);
     
            ftf.setFormatterFactory(
                  new DefaultFormatterFactory(intFormatter));
           // ftf.setValue(15);
            //ftf.setHorizontalAlignment(JTextField.TRAILING);
            //ftf.setFocusLostBehavior(JFormattedTextField.PERSIST);
     
            //React when the user presses Enter while the editor is
            //active.  (Tab is handled as specified by
            //JFormattedTextField's focusLostBehavior property.)
            ftf.getInputMap().put(KeyStroke.getKeyStroke(
                                            KeyEvent.VK_ENTER, 0),
                                            "check");
            ftf.getActionMap().put("check", new AbstractAction() {
                public void actionPerformed(ActionEvent e) {
    		if (!ftf.isEditValid()) { //The text is invalid.
                        if (userSaysRevert()) { //reverted
    		        ftf.postActionEvent(); //inform the editor
    		    }
                    } else try {              //The text is valid,
                        ftf.commitEdit();     //so use it.
                        ftf.postActionEvent(); //stop editing
                    } catch (java.text.ParseException exc) { }
                }
            });
        }
     
        //Override to invoke setValue on the formatted text field.
        public Component getTableCellEditorComponent(JTable table,
                Object value, boolean isSelected,
                int row, int column) {
            JFormattedTextField ftf =
                (JFormattedTextField)super.getTableCellEditorComponent(
                    table, value, isSelected, row, column);
            ftf.setValue(value);
            return ftf;
        }
     
        //Override to ensure that the value remains an Integer.
        public Object getCellEditorValue() {
            JFormattedTextField ftf = (JFormattedTextField)getComponent();
            Object o = ftf.getValue();
            if (o instanceof Double) {
                return o;
            } else if (o instanceof Number) {
                return new Double(((Number)o).doubleValue());
            } else {
                if (DEBUG) {
                    System.out.println("getCellEditorValue: o isn't a Number");
                }
                try {
                    return integerFormat.parseObject(o.toString());
                } catch (ParseException exc) {
                    System.err.println("getCellEditorValue: can't parse o: " + o);
                    return null;
                }
            }
        }
     
        //Override to check whether the edit is valid,
        //setting the value if it is and complaining if
        //it isn't.  If it's OK for the editor to go
        //away, we need to invoke the superclass's version 
        //of this method so that everything gets cleaned up.
        public boolean stopCellEditing() {
            JFormattedTextField ftf = (JFormattedTextField)getComponent();
            if (ftf.isEditValid()) {
                try {
                    ftf.commitEdit();
                } catch (java.text.ParseException exc) { }
     
            } else { //text is invalid
                if (!userSaysRevert()) { //user wants to edit
    	        return false; //don't let the editor go away
    	    } 
            }
            return super.stopCellEditing();
        }
     
        /** 
         * Lets the user know that the text they entered is 
         * bad. Returns true if the user elects to revert to
         * the last good value.  Otherwise, returns false, 
         * indicating that the user wants to continue editing.
         */
        protected boolean userSaysRevert() {
            Toolkit.getDefaultToolkit().beep();
            ftf.selectAll();
            Object[] options = {"Edit",
                                "Revert"};
            int answer = JOptionPane.showOptionDialog(
                SwingUtilities.getWindowAncestor(ftf),
                "The value must be an integer between "
                + minimum + " and "
                + maximum + ".\n"
                + "You can either continue editing "
                + "or revert to the last valid value.",
                "Invalid Text Entered",
                JOptionPane.YES_NO_OPTION,
                JOptionPane.ERROR_MESSAGE,
                null,
                options,
                options[1]);
     
            if (answer == 1) { //Revert!
                ftf.setValue(ftf.getValue());
    	    return true;
            }
    	return false;
        }
    }
    Merci

  2. #2
    Membre éclairé Avatar de lastrecrue
    Développeur Java
    Inscrit en
    Février 2006
    Messages
    360
    Détails du profil
    Informations personnelles :
    Âge : 43

    Informations professionnelles :
    Activité : Développeur Java

    Informations forums :
    Inscription : Février 2006
    Messages : 360
    Par défaut
    essai en filtrant que les positifs dans la méthode getCellEditorValue().

  3. #3
    Membre confirmé
    Inscrit en
    Juin 2007
    Messages
    68
    Détails du profil
    Informations forums :
    Inscription : Juin 2007
    Messages : 68
    Par défaut
    Les nombres positifs sont filtrés par
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    minimum = new Double(0.0);
    Par contre le seul problème c'est que 5.243 devient 5 alors que je voudrais 5.243 donne 5.243 (par de fonction tronquer...)

    Merci

  4. #4
    Membre éclairé Avatar de lastrecrue
    Développeur Java
    Inscrit en
    Février 2006
    Messages
    360
    Détails du profil
    Informations personnelles :
    Âge : 43

    Informations professionnelles :
    Activité : Développeur Java

    Informations forums :
    Inscription : Février 2006
    Messages : 360
    Par défaut
    tu peu regarder ça http://java.developpez.com/faq/java/...haine_formatee je crois que ca pourras t'aider.

  5. #5
    Membre confirmé
    Inscrit en
    Juin 2007
    Messages
    68
    Détails du profil
    Informations forums :
    Inscription : Juin 2007
    Messages : 68
    Par défaut
    Merci pour le lien.

    En effet, quand je modifie le DecimalFormat en ajoutant : Locale.US

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
     integerFormat = (DecimalFormat)NumberFormat.getInstance(Locale.US);
    Les doubles avec le séparateur décimal '.' (point) sont bien gardés, ce qui est le but de la manœuvre.

    Par contre que serait le moyen le plus propre pour ne pas accepter le séparateur décimal ','. car la méthode Parse cesse dès qu'elle rencontre un caractère qui n'est pas un nombre . Exemple 5,34 donne 534 à cause/grace à (Locale.US) et 5p34 donne 5 (méthode Parse)

    Je souhaiterais que 5,34 donne 5.34 ( remplacement automatique de la virgule ou au moins un message d'avertissement si un caractère autre qu'un chiffre est détecté).

    Pour un JtextField cela se fait bien avec un InputVerifier mais pour une JTable, il faut utiliser un DefaultCellEditor...mais pas d'exemple se dans la doc

    Merci

  6. #6
    Membre éclairé Avatar de lastrecrue
    Développeur Java
    Inscrit en
    Février 2006
    Messages
    360
    Détails du profil
    Informations personnelles :
    Âge : 43

    Informations professionnelles :
    Activité : Développeur Java

    Informations forums :
    Inscription : Février 2006
    Messages : 360
    Par défaut
    quand tu saisi quelque chose de non décimal tu n'a aucun message d'erreur ?

  7. #7
    Membre confirmé
    Inscrit en
    Juin 2007
    Messages
    68
    Détails du profil
    Informations forums :
    Inscription : Juin 2007
    Messages : 68
    Par défaut
    Si je saisie 5p cela donne sans message d'erreur : 5 (normale la méthode Parse s'arrete au premier caractere qui n'est pas un nombre.

    Si je saisie p5 cela donne erreur, normale car le premier caractère n'est pas un nombre.

    N existe t-il pas un moyen de définir une Locale avec plusieurs separateurs. Dans mon cas je souhaiterais ajouter le point comme separateur à la locale Locale.French, tout en gardant la virgule comme séprateur

    Merci

  8. #8
    Membre éclairé Avatar de lastrecrue
    Développeur Java
    Inscrit en
    Février 2006
    Messages
    360
    Détails du profil
    Informations personnelles :
    Âge : 43

    Informations professionnelles :
    Activité : Développeur Java

    Informations forums :
    Inscription : Février 2006
    Messages : 360
    Par défaut
    regard ou ca parse, tu change les . par des , ou vis ver ca juste avant ???

  9. #9
    Expert éminent
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Billets dans le blog
    1
    Par défaut
    Salut,


    Le parse() s'arrête au premier caractère incorrect sans générer d'erreur. Ce comportement est tout à fait normal et permet de traiter des chaines complexes sans avoir forcément à les découper avant...

    Si tu ne souhaites pas ce comportement il faut utiliser le ParsePosition pour générer une erreur si la chaine n'est pas traité en entier. Exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    	public static Number parseAll(NumberFormat nf, String source) throws ParseException {
    		ParsePosition pp = new ParsePosition(0);
    		Number number = nf.parse(source, pp);
    		// On vérifie qu'il n'y ai pas eu d'erreur :
    		if (pp.getIndex() == 0 || pp.getErrorIndex() >= 0) {
                throw new ParseException("Unparseable number: \"" + source + "\"",
                                         pp.getErrorIndex());
            }
    		// On vérifie que toute la chaine ait bien été lu :
    		if (pp.getIndex() != source.length()) {
    			throw new ParseException("Unparseable number: \"" + source + "\"",
                        pp.getIndex());
    		}
    		return number;
    	}

    Pour le reste comme indiqué il suffit d'effectuer une petit remplacement avec de traiter la chaine...

    a++

  10. #10
    Membre confirmé
    Inscrit en
    Juin 2007
    Messages
    68
    Détails du profil
    Informations forums :
    Inscription : Juin 2007
    Messages : 68
    Par défaut
    ok merci

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Séparateur pour une JTable
    Par Liiinz dans le forum Agents de placement/Fenêtres
    Réponses: 13
    Dernier message: 29/08/2011, 13h41
  2. Fusion de cellules pour une JTABLE
    Par niggaz972 dans le forum Composants
    Réponses: 10
    Dernier message: 30/07/2009, 18h13
  3. Affichage d'un Double dans une JTable
    Par Brice22 dans le forum Composants
    Réponses: 1
    Dernier message: 16/03/2009, 17h38
  4. ArrayList ou Tableau pour une JTable
    Par bandit_debutant dans le forum Composants
    Réponses: 2
    Dernier message: 12/06/2008, 13h28
  5. Besoin d'aide pour une jTable
    Par Sh4dounet dans le forum Composants
    Réponses: 2
    Dernier message: 13/03/2007, 18h23

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo