JSpinner Значение изменения События - PullRequest
33 голосов
/ 16 октября 2010

Как выполнить обновление сразу после изменения значения jSpinner.

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

spinner1.addChangeListener(listener);

Приведенный выше код не изменяет текст метки автоматически, он требует повторного нажатия в любом месте для обновления.

Ответы [ 6 ]

44 голосов
/ 28 сентября 2011

Ответ заключается в настройке форматера, используемого в JFormattedTextField, который является потомком редактора счетчика:

    formatter.setCommitsOnValidEdit(true);

К сожалению, взять его за руку так же долго и грязно, как и вступительное предложение:

    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());
        }
    });

Немного (но не намного) более чистый способ может заключаться в создании подкласса NumberEditor и предоставлении метода, который позволяет настройку

8 голосов
/ 16 октября 2010

Код, который вы показываете, отображается правильно. Для справки вот рабочий пример.

Добавление: пока фокусировка у JSpinner, клавиши курсора влево и вправо перемещают каретку. Стрелка вверх увеличивается, а стрелка вниз уменьшает поле, содержащее курсор. Изменение (эффективно) происходит одновременно как на счетчике, так и на этикетке.

Чтобы получить доступ к JFormattedTextField из JSpinner.DateEditor, используйте метод родителя getTextField(). Подходящий слушатель каретки или слушатель ввода текста может затем использоваться для обновления метки по желанию.

Добавление: обновление для использования setCommitsOnValidEdit, как предлагается здесь .

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 https://stackoverflow.com/questions/2010819
 * @see https://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);
    }
}
3 голосов
/ 08 июня 2011

Проблема здесь в том, что когда вы редактируете значение JSpinner вручную, печатая с клавиатуры, событие stateChanged не запускается до тех пор, пока фокус не будет потерян JSpinner или пока не будет нажата клавиша Enter.

Если вы хотите загрузить значение, необходим KeyListener, который будет выполнять setValue в JSpinner для каждого набранного ключа.

Я оставлю здесь пример для JSpinner с 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
        }
    }
});
2 голосов
/ 15 октября 2016

Это может быть поздний ответ, но вы можете использовать мой подход.
Поскольку spuas , о котором говорилось выше, проблема заключается в том, что событие stateChanged запускается только при потере фокуса или нажатии клавиши Enter.
Использование KeyListeners также не очень хорошая идея.
Было бы лучше использовать DocumentListener вместо этого.Я немного изменил пример spuas, и вот что я получил:

JSpinner spinner= new JSpinner();
spinner.setModel(new SpinnerNumberModel(0, 0, Integer.MAX_VALUE, 1));
final JTextField jtf = ((JSpinner.DefaultEditor) spinner.getEditor()).getTextField();
        jtf.getDocument().addDocumentListener(new DocumentListener() {              

        private volatile int value = 0;

        @Override
        public void removeUpdate(DocumentEvent e) {
            showChangedValue(e);    
        }

        @Override
        public void insertUpdate(DocumentEvent e) {
            showChangedValue(e);                
        }

        @Override
        public void changedUpdate(DocumentEvent e) {
            showChangedValue(e);    
        }

        private void showChangedValue(DocumentEvent e){
            try {
                String text = e.getDocument().getText(0, e.getDocument().getLength());
                if (text==null || text.isEmpty()) return;
                    int val = Integer.parseInt(text).getValue();
                if (value!=val){
                   System.out.println(String.format("changed  value: %d",val));             
                   value = val;
                }       
            } catch (BadLocationException | NumberFormatException e1) {
                          //handle if you want
            }        
       }
});
1 голос
/ 02 февраля 2017

Последний ответ можно немного изменить, чтобы сделать его более гибким. Вы можете просто использовать этот новый MyJSpinner вместо любого JSpinner. Самое большое изменение заключается в том, что вы можете использовать эту новую версию с любой базовой моделью JSpinner (int, double, byte и т. Д.)

    public class MyJSpinner extends JSpinner{
        boolean setvalueinprogress=false;
        public MyJSpinner()
        {
            super();
            final JTextField jtf = ((JSpinner.DefaultEditor) getEditor()).getTextField();
            jtf.getDocument().addDocumentListener(new DocumentListener() {              

                    @Override
                    public void removeUpdate(DocumentEvent e) {
                        showChangedValue(e);    
                    }

                    @Override
                    public void insertUpdate(DocumentEvent e) {
                        showChangedValue(e);                
                    }

                    @Override
                    public void changedUpdate(DocumentEvent e) {
                        showChangedValue(e);    
                    }

                    private void showChangedValue(DocumentEvent e){
                        try {
                            if (!setvalueinprogress)
                                MyJSpinner.this.commitEdit();      
                        } catch (NumberFormatException | ParseException ex) {
                                      //handle if you want
                            Exceptions.printStackTrace(ex);
                        }      
                   }
            });
        }

    @Override
    public void setValue(Object value) {
        setvalueinprogress=true;
        super.setValue(value); 
        setvalueinprogress=false;
    }

 }
0 голосов
/ 01 августа 2016

Я новичок, поэтому могу нарушать некоторые правила и опоздать. Но некоторые ответы показались мне немного запутанными, поэтому я поиграл в IDE NetBeans и обнаружил, что если вы щелкнете правой кнопкой мыши на компоненте GUI jspinner, размещенном на вашей jform, и перейдете в раздел events-> change, для вас будет сгенерирован код.

...