web-dev-qa-db-ja.com

JSpinner値変更イベント

JSpinner値が変更されたときにすぐに更新する方法。

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

spinner1.addChangeListener(listener);

上記のコードはラベルテキストを自動的に変更しません。更新するにはどこでももう一度クリックする必要があります。

34
user236501

答えは、スピナーのエディターの子である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をサブクラス化し、構成を許可するメソッドを公開することです。

44
kleopatra

ここでの問題は、キーボードから入力してJSpinner値を手動で編集すると、stateChangedによってフォーカスが失われるか、Enterキーが押されるまでJSpinnerイベントが発生しないことです。押されました。

値をアップロードする場合は、入力されたキーごとにKeyListenersetValueを実行するJSpinnerが必要です。

JSpinnerSpinnerNumberModelの例をここに残します:

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
        }
    }
});
3
spuas

それは遅い答えかもしれませんが、あなたは私のアプローチを使うかもしれません。
As 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
            }        
       }
});
2
rvit34

最後の答えは、少し柔軟に変更できるように、少し並べ替えることができます。 JSpinnerの代わりに、この新しいMyJSpinnerを使用するだけです。最大の変更点は、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;
    }

 }
1

私は新しいので、いくつかの規則に違反している可能性があり、遅れる可能性があります。しかし、いくつかの答えが少しわかりにくいので、NetBeansで遊んでみましたIDEコードが生成されます。

0
Isidore Bennett