---
category: swing
folder: RoundDownToHalfSpinner
title: JSpinnerの数値を0.5単位で切り捨てる
tags: [JSpinner, JFormattedTextField]
author: aterai
pubdate: 2025-02-10T03:12:04+09:00
description: JSpinnerに表示する数値を0.5単位で切り捨て、または四捨五入するよう設定します。
image: https://drive.google.com/uc?id=1NUCQ7kUpaVRdhJC4OGlXAQwU0x-FdRnZ
---
* Summary [#summary]
JSpinnerに表示する数値を0.5単位で切り捨て、または四捨五入するよう設定します。
`JSpinner`に表示する数値を`0.5`単位で切り捨て、または四捨五入するよう設定します。

#download(https://drive.google.com/uc?id=1NUCQ7kUpaVRdhJC4OGlXAQwU0x-FdRnZ)

* Source Code Examples [#sourcecode]
#code(link){{
private static DefaultFormatter makeDownFormatter() {
  return new DefaultFormatter() {
    @Override public Object stringToValue(String text) {
      return roundToDown(new BigDecimal(text)).doubleValue();
   }

   @Override public String valueToString(Object value) {
      return roundToDown(BigDecimal.valueOf((Double) value)).toString();
    }
  };
}

private static BigDecimal roundToDown(BigDecimal value) {
  return value.multiply(BigDecimal.valueOf(2))
      .setScale(0, RoundingMode.DOWN)
      .multiply(BigDecimal.valueOf(.5));
}
}}

* Explanation [#explanation]
- `Default, stepSize: 0.5`
-- デフォルトの`SpinnerNumberModel`にステップサイズを`0.5`として使用
-- 矢印ボタンで`JSpinner`の数値を変更すると`0.5`単位で増減するが、たとえば直接`8.85`を入力しても`0.5`単位の端数処理などは適用されない

- `Override SpinnerNumberModel`
-- `SpinnerNumberModel#setValue(...)`メソッドをオーバーライドして値を`0.5`単位で切り捨て
-- コンストラクタで初回の現在値を設定する場合は`SpinnerNumberModel#setValue(...)`が使用されないので、`super(roundDownToHalf(value), min, max, step);`のように切り捨てを実行している

#code{{
class RoundToHalfSpinnerModel extends SpinnerNumberModel {
  protected RoundToHalfSpinnerModel(
      double value, double min, double max, double step) {
    super(roundDownToHalf(value), min, max, step);
  }

  @Override public void setValue(Object value) {
    if (value instanceof Double) {
      Double v = roundDownToHalf((Double) value);
      if (!v.equals(getValue())) {
        super.setValue(v);
        fireStateChanged();
      }
    } else {
      throw new IllegalArgumentException("illegal value");
    }
  }

  private static double roundDownToHalf(Double value) {
    return BigDecimal.valueOf(value)
        .multiply(BigDecimal.valueOf(2))
        .setScale(0, RoundingMode.DOWN)
        .multiply(BigDecimal.valueOf(.5))
        .doubleValue();
  }
}
}}

- `Round down to half Formatter`
-- `JSpinner.DefaultEditor`から`JFormattedTextField`を取得して、`0.5`単位で切り捨てを実行する`DefaultFormatterFactory`を設定
-- `0.5`単位の切り捨ては、`BigDecimal`の値を`2`倍したあと`BigDecimal#setScale(0, RoundingMode.DOWN)`で小数点以下を切り捨てし、`0.5`倍することで実行している

- `Round to half Formatter`
-- `JSpinner.DefaultEditor`から`JFormattedTextField`を取得して、`0.5`単位で四捨五入をを実行する`DefaultFormatterFactory`を設定
-- `0.5`単位の四捨五入は、`BigDecimal`の値を`2`倍したあと`BigDecimal#setScale(0, RoundingMode.HALF_UP)`で小数点以下を四捨五入し、`0.5`倍することで実行している
 
* Reference [#reference]
- [[JSpinnerの上下限値をBigDecimalで比較する>Swing/BigDecimalSpinnerModel]]
- [[JColorChooserのRGB色選択パネル内に表示される16進数カラーコードにAlpha値を追加する>Swing/ColorChooserRgbaHexCode]]

* Comment [#comment]
#comment
#comment