27 votes

Événements de changement de valeur JSpinner

Comment effectuer la mise à jour immédiatement lorsque la valeur jSpinner a été modifiée.

 ChangeListener listener = new ChangeListener() {
  public void stateChanged(ChangeEvent e) {
    jLabel.setText(e.getSource());
  }
};

spinner1.addChangeListener(listener);
 

Le code ci-dessus ne modifie pas automatiquement le texte de l'étiquette, il vous obligeait à cliquer à nouveau n'importe où pour mettre à jour.

38voto

kleopatra Points 31585

La réponse est de configurer le formateur utilisé dans le JFormattedTextField qui est un enfant de l'éditeur du spinner:

     formatter.setCommitsOnValidEdit(true);
 

Malheureusement, mettre la main dessus est aussi long et sale que la phrase introductive:

     final JSpinner spinner = new JSpinner();
    JComponent comp = spinner.getEditor();
    JFormattedTextField field = (JFormattedTextField) comp.getComponent(0);
    DefaultFormatter formatter = (DefaultFormatter) field.getFormatter();
    formatter.setCommitsOnValidEdit(true);
    spinner.addChangeListener(new ChangeListener() {

        @Override
        public void stateChanged(ChangeEvent e) {
            LOG.info("value changed: " + spinner.getValue());
        }
    });
 

Un moyen légèrement (mais pas beaucoup) plus propre pourrait être de sous-classer NumberEditor et d'exposer une méthode qui permet la config

5voto

trashgod Points 136305

Le code vous montrer s'affiche correctement. Pour référence, voici un exemple de travail.

Addendum: Alors que l' JSpinner a le focus, gauche et droite les touches fléchées pour déplacer le curseur. La flèche vers le haut incréments et la flèche vers le bas décrémente le champ contenant le curseur. Le changement est (effectivement) simultanée dans les deux de la toupie et de l'étiquette.

Pour accéder à l' JFormattedTextField de la JSpinner.DateEditor, l'utilisation de la société mère getTextField() méthode. Approprié signe auditeur ou de saisie de texte auditeur peut alors être utilisé pour mettre à jour l'étiquette souhaitée.

Addendum: mise à Jour pour utiliser setCommitsOnValidEdit, comme suggéré ici.

import java.awt.EventQueue;
import java.awt.GridLayout;
import java.util.Calendar;
import java.util.Date;
import javax.swing.JFormattedTextField;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSpinner;
import javax.swing.JSpinner.DateEditor;
import javax.swing.SpinnerDateModel;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.text.DefaultFormatter;

/**
 * @see http://stackoverflow.com/questions/2010819
 * @see http://stackoverflow.com/questions/3949518
 */
public class JSpinnerTest extends JPanel {

    public static void main(String args[]) {
        EventQueue.invokeLater(new Runnable() {

            @Override
            public void run() {
                JFrame f = new JFrame("JSpinnerTest");
                f.add(new JSpinnerTest());
                f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                f.pack();
                f.setVisible(true);
            }
        });
    }

    public JSpinnerTest() {
        super(new GridLayout(0, 1));
        final JLabel label = new JLabel();
        final JSpinner spinner = new JSpinner();
        Calendar calendar = Calendar.getInstance();
        Date initDate = calendar.getTime();
        calendar.add(Calendar.YEAR, -5);
        Date earliestDate = calendar.getTime();
        calendar.add(Calendar.YEAR, 10);
        Date latestDate = calendar.getTime();
        spinner.setModel(new SpinnerDateModel(
            initDate, earliestDate, latestDate, Calendar.MONTH));
        DateEditor editor = new JSpinner.DateEditor(spinner, "MMM yyyy");
        spinner.setEditor(editor);
        JFormattedTextField jtf = editor.getTextField();
        DefaultFormatter formatter = (DefaultFormatter) jtf.getFormatter();
        formatter.setCommitsOnValidEdit(true);
        spinner.addChangeListener(new ChangeListener() {

            @Override
            public void stateChanged(ChangeEvent e) {
                JSpinner s = (JSpinner) e.getSource();
                label.setText(s.getValue().toString());
            }
        });
        label.setText(initDate.toString());
        this.add(spinner);
        this.add(label);
    }
}

2voto

spuas Points 654

Le problème ici est que lorsque vous modifiez l' JSpinner de la valeur manuellement en tapant sur le clavier, l' stateChanged événement n'est pas déclenché, jusqu'à ce que le focus est perdu par l' JSpinner ou jusqu'à ce que touche Entrée.

Si vous voulez télécharger de la valeur, une KeyListener est nécessaire, qui va effectuer un setValue dans la JSpinner pour chaque clé tapé.

Je laisse un exemple ici pour un JSpinner avec un SpinnerNumberModel:

JSpinner spinner= new JSpinner();
spinner.setModel(new SpinnerNumberModel(0, 0, Integer.MAX_VALUE, 1));
spinner.addChangeListener(new ChangeListener() {
    @Override
    public void stateChanged(ChangeEvent e) {
        jLabel.setText(spinner.getValue());
    }
});
final JTextField jtf = ((JSpinner.DefaultEditor) spinner.getEditor()).getTextField();
jtf.addKeyListener(new KeyAdapter() {
    @Override
    public void keyReleased(KeyEvent e) {
        String text = jtf.getText().replace(",", "");
        int oldCaretPos = jtf.getCaretPosition();
        try {
            Integer newValue = Integer.valueOf(text);
            spinner.setValue(newValue);
            jtf.setCaretPosition(oldCaretPos);
        } catch(NumberFormatException ex) {
            //Not a number in text field -> do nothing
        }
    }
});

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X