• category: swing folder: NumberFormatter title: JSpinnerで無効な値の入力を許可しない tags: [JSpinner, JFormattedTextField, SpinnerNumberModel, DocumentListener, NumberFormatter] author: aterai pubdate: 2010-03-08T15:39:14+09:00 description: JSpinnerからJFormattedTextFieldを取得し、これに無効な値の入力を許可しないように設定します。 image: https://lh5.googleusercontent.com/_9Z4BYR88imo/TQTQg6Td8tI/AAAAAAAAAfs/u5mXLfk3k64/s800/NumberFormatter.png

概要

JSpinnerからJFormattedTextFieldを取得し、これに無効な値の入力を許可しないように設定します。

サンプルコード

JSpinner.NumberEditor editor = (JSpinner.NumberEditor) spinner.getEditor();
JFormattedTextField.AbstractFormatter formatter = editor.getTextField().getFormatter();
if (formatter instanceof DefaultFormatter) {
  ((DefaultFormatter) formatter).setAllowsInvalid(false);
}
View in GitHub: Java, Kotlin

解説

上記のサンプルでは、DefaultFormatter#setAllowsInvalid(false)などを設定したDefaultFormatterFactoryを作成して、JSpinnerから取得したJFormattedTextFieldsetFormatterFactoryで追加しています。

    • SpinnerNumberModelを設定した通常のJSpinner
    • 別コンポーネントにフォーカスが移動するときに、値が有効か無効かを判断
    • SpinnerNumberModelを設定し、数値以外の無効な文字入力ができないようにしたJSpinner
    • SpinnerNumberModelを設定した通常のJSpinner
    • 別コンポーネントにフォーカスが移動するときに、値が有効か無効かを判断
    • 無効な値の場合は、背景色を変更
private static JSpinner makeSpinner2(SpinnerNumberModel m) {
  JSpinner s = new JSpinner(m);
  JSpinner.NumberEditor editor = (JSpinner.NumberEditor) s.getEditor();
  final JFormattedTextField ftf = (JFormattedTextField) editor.getTextField();
  ftf.setFormatterFactory(makeFFactory(m));
  ftf.getDocument().addDocumentListener(new DocumentListener() {
    private final Color color = new Color(255, 200, 200);
    @Override public void changedUpdate(DocumentEvent e) {
      updateEditValid();
    }
    @Override public void insertUpdate(DocumentEvent e) {
      updateEditValid();
    }
    @Override public void removeUpdate(DocumentEvent e) {
      updateEditValid();
    }
    private void updateEditValid() {
      EventQueue.invokeLater(new Runnable() {
        @Override public void run() {
          ftf.setBackground(ftf.isEditValid() ? Color.WHITE : color);
        }
      });
    }
  });
  return s;
}
private static DefaultFormatterFactory makeFFactory(final SpinnerNumberModel m) {
  final NumberFormat format = new DecimalFormat("####0");
  NumberFormatter displayFormatter = new NumberFormatter(format);
  NumberFormatter editFormatter = new NumberFormatter(format) {
    @Override public Object stringToValue(String text) throws ParseException {
      try {
        Long.parseLong(text);
      } catch (NumberFormatException e) {
        throw new ParseException("xxx", 0);
      }
      Object o = format.parse(text);
      if (o instanceof Long) {
        Long val = (Long) format.parse(text);
        Long max = (Long) m.getMaximum();
        Long min = (Long) m.getMinimum();
        if (max.compareTo(val) < 0 || min.compareTo(val) > 0) {
          throw new ParseException("xxx", 0);
        }
        return val;
      }
      throw new ParseException("xxx", 0);
    }
  };
  //editFormatter.setAllowsInvalid(false);
  //editFormatter.setCommitsOnValidEdit(true);
  editFormatter.setValueClass(Long.class);
  return new DefaultFormatterFactory(displayFormatter, displayFormatter, editFormatter);
}

参考リンク

コメント