import java.awt.BorderLayout;
import java.text.*;
import javax.swing.*;
import javax.swing.JFormattedTextField.AbstractFormatter;
import javax.swing.text.*;
public class Spinner extends JFrame {
/** メイン */
public static void main(String[] args) {
Spinner f = new Spinner("Spinner");
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
}
/** コンストラクタ */
public Spinner(String title) {
super(title);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
getContentPane().add(getSpinner());
getContentPane().add(new JButton("hoge"), BorderLayout.SOUTH);
}
/** スピナー生成 */
private JSpinner getSpinner() {
final SpinnerNumberModel model =
new SpinnerNumberModel(0.000000, -50.000000, 50.000000, 0.023023);
final JSpinner spinner = new JSpinner(model);
spinner.setEditor(new SpinnerEditor2(spinner, "0.000"));
return spinner;
}
/** 自作NumberEditorFormatterクラス */
private static class MyNumberEditorFormatter
extends InternationalFormatter {
private final SpinnerNumberModel model;
MyNumberEditorFormatter(
SpinnerNumberModel model,
NumberFormat format) {
super(format);
this.model = model;
setValueClass(model.getValue().getClass());
}
public Comparable getMaximum() {
return model.getMaximum();
}
public Comparable getMinimum() {
return model.getMinimum();
}
public void setMaximum(Comparable max) {
model.setMaximum(max);
}
public void setMinimum(Comparable min) {
model.setMinimum(min);
}
/**
* 文字列→値変換メソッドをオーバーライドする。
* 範囲外の時は、値を最大値、または最小値に修正する。
* @see javax.swing.text.InternationalFormatter#stringToValue(java.lang.String)
*/
public Object stringToValue(String text) throws ParseException {
try {
return super.stringToValue(text);
}
catch (ParseException e) {
// 範囲外の場合、ParseExceptionが投げられるのでキャッチする。
Object object = getFormat().parseObject(text);
Double d;
if (object instanceof Double) {
d = (Double)object;
}
else if (object instanceof Number) {
d = new Double(((Number)object).doubleValue());
}
else {
throw e;
}
if (getMaximum().compareTo(d) < 0) {
// 最大を超えている場合は、最大値を返す。
return getMaximum();
}
else if (getMinimum().compareTo(d) > 0) {
// 最小に満たない場合は、最小値を返す。
return getMinimum();
}
else {
throw e;
}
}
}
}
private static class SpinnerEditor2 extends JSpinner.NumberEditor {
/**
* コンストラクタ
* @param spinner
* @param decimalFormatPattern
*/
public SpinnerEditor2(JSpinner spinner, String decimalFormatPattern) {
super(spinner, decimalFormatPattern);
// Formatterを自作のものに変更する。
MyNumberEditorFormatter formatter =
new MyNumberEditorFormatter(
(SpinnerNumberModel)spinner.getModel(),
new DecimalFormat(decimalFormatPattern));
DefaultFormatterFactory factory =
new DefaultFormatterFactory(formatter);
getTextField().setFormatterFactory(factory);
}
/* (non-Javadoc) override
* @see javax.swing.JSpinner.DefaultEditor#commitEdit()
*/
public void commitEdit() throws ParseException {
Object old = getModel().getValue();
String newStr = getTextField().getText();
try {
AbstractFormatter formatter = getTextField().getFormatter();
String oldStr = formatter.valueToString(old);
// 頭の部分が変わってなかったら、変更しない
if (newStr.startsWith(oldStr)) {
return;
}
}
catch (ParseException e) {
// 起こらないハズ
e.printStackTrace();
}
// 変更を確定させる。
super.commitEdit();
}
}
}
|