问题
I would like to allow both "comma" and "dot" as separator in double.
I could use replace method in string to get only one separator, but problem is that double value is value of JSpinner and I was not able to find any method to allow both separators. If I set locale for example to French only one separator is allowed.
回答1:
Just use a custom formatter for the JFormattedTextField
of the DefaultEditor
of the JSpinner
, like the code below:
import java.text.ParseException;
import javax.swing.JFormattedTextField;
import javax.swing.JFormattedTextField.AbstractFormatter;
import javax.swing.JFormattedTextField.AbstractFormatterFactory;
import javax.swing.JFrame;
import javax.swing.JSpinner;
import javax.swing.JSpinner.DefaultEditor;
import javax.swing.SpinnerNumberModel;
public class Main {
public static class CommmaDotFormatter extends AbstractFormatter {
private boolean useComma = false;
@Override
public Object stringToValue(String text) throws ParseException {
if (text == null || text.trim().isEmpty())
throw new ParseException("Null or empty text.", 0);
try {
useComma = (text.contains(",") && (text.indexOf(',') == text.lastIndexOf(',')));
return Double.valueOf(useComma? text.replace(',', '.'): text);
}
catch (final NumberFormatException nfx) {
//Find the location of the error (so as to generate appropriate ParseException):
int i = 0;
for (final int cp: text.codePoints().toArray()) {
if (!Character.isDigit(cp) && cp != ',' && cp != '.')
throw new ParseException("Failed to parse text \"" + text + "\".", i);
++i;
}
//Could happen if the text is composed by digits and more than one dot/comma:
throw new ParseException("Failed to parse text \"" + text + "\".", 0);
}
}
@Override
public String valueToString(final Object value) throws ParseException {
final String text = String.format("%.2f", value);
return useComma? text: text.replace(',', '.');
}
}
public static class CommmaDotFormatterFactory extends AbstractFormatterFactory {
@Override
public AbstractFormatter getFormatter(final JFormattedTextField tf) {
if (!(tf.getFormatter() instanceof CommmaDotFormatter))
return new CommmaDotFormatter();
return tf.getFormatter();
}
}
public static void main(final String[] args) {
final JSpinner spin = new JSpinner(new SpinnerNumberModel(0, -10, 10, 0.01));
((DefaultEditor) spin.getEditor()).getTextField().setFormatterFactory(new CommmaDotFormatterFactory());
final JFrame frame = new JFrame("JSpinner infinite value");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(spin);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
Note: property useComma
could be omitted. It simply exists to maintain the state of the last input of the user. For example if the user enters a value with comma rather than dot, then the spinner will keep spinning with commas. Same for dots. Whatever the user types will remain for future values, and of course it can be changed again any time by him/her. But your question can be satisfied even without this property: you would just have to do text.replace(',', '.')
each time the given text in stringToValue
before parsing it into a double
.
来源:https://stackoverflow.com/questions/30855805/jspinner-and-double-with-dot-or-comma-as-separator