Подтвердить что ты не робот

События изменения стоимости JSpinner

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

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

spinner1.addChangeListener(listener);

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

4b9b3361

Ответ 1

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

    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 и выставить метод, который позволяет config

Ответ 2

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

Приложение: В то время как 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

Проблема заключается в том, что когда вы редактируете значение 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
        }
    }
});

Ответ 4

Это может быть поздний ответ, но вы можете использовать мой подход. Как упоминалось выше, проблема заключается в том, что событие 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
            }        
       }
});

Ответ 5

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

Ответ 6

Последний ответ можно немного перестроить, чтобы сделать его немного более гибким. Вы можете просто использовать этот новый 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;
    }

 }