3 回答
TA贡献1840条经验 获得超5个赞
这是我能够使用 FocusListener 开始工作的解决方案,尽管我不确定它的正确性。
private JFormattedTextField tf = ((JSpinner.DefaultEditor) jSpinnerTiming.getEditor()).getTextField();
((JSpinner.DefaultEditor)jSpinnerTiming.getEditor()).getTextField().addFocusListener(new FocusListener() {
@Override
public void focusLost(FocusEvent e) {
// The unchecked user input value
double dirtyValue = Double.parseDouble(tf.getText());
// Get Minimum and Maximum values from jSpinner's Model
double max = (Double) ((SpinnerNumberModel) jSpinnerTiming.getModel()).getMaximum();//MAX_ALLOWED_RATE
double min = (Double) ((SpinnerNumberModel) jSpinnerTiming.getModel()).getMinimum();//LOWEST_ALLOWABLE_RATE;
if (dirtyValue > max) {
jSpinnerTiming.setValue(max);
} else if(dirtyValue < min){
jSpinnerTiming.setValue(min);
}
}
@Override
public void focusGained(FocusEvent e) {
// TODO Auto-generated method stub
}
});
TA贡献1744条经验 获得超4个赞
问题是 JSpinner 将所有内容都保留在内部。编辑器安装了一个AbstractFormatter,它永远不允许低于最小值或高于最大值,因此您永远没有机会对这些条件做出反应。
由于拦截现有 AbstractFormatter 的行为几乎是不可能的,因此我只创建没有最小值或最大值的 JSpinner,并在 ChangeListener 中手动强制执行这些边界:
private static JSpinner createSpinner() {
double initialValue = 20;
SpinnerModel model =
new SpinnerNumberModel(initialValue, null, null, 1d);
model.addChangeListener(e -> {
double value = ((Number) model.getValue()).doubleValue();
if (value < ALLOWABLE_MIN) {
EventQueue.invokeLater(() -> model.setValue(ALLOWABLE_MIN));
} else if (value > ALLOWABLE_MAX) {
EventQueue.invokeLater(() -> model.setValue(ALLOWABLE_MAX));
}
});
return new JSpinner(model);
}
TA贡献1802条经验 获得超4个赞
您还可以更改的(AbstractFormatter通过自定义),如以下代码:JFormattedTextFieldDefaultEditorJSpinnerAbstractFormatterFactory
import java.awt.Dimension;
import java.text.ParseException;
import java.util.Objects;
import javax.swing.JButton;
import javax.swing.JFormattedTextField;
import javax.swing.JFormattedTextField.AbstractFormatter;
import javax.swing.JFormattedTextField.AbstractFormatterFactory;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JSpinner;
import javax.swing.JSpinner.DefaultEditor;
import javax.swing.SpinnerNumberModel;
public class Main {
public static class IntegerFormatter extends AbstractFormatter {
private final int min, max;
public IntegerFormatter(final int min, final int max) {
this.min = min;
this.max = max;
}
@Override
public Object stringToValue(final String text) throws ParseException {
try {
//This is where we compare for out of bounds values:
final int val = Integer.parseInt(text);
if (val < min)
return min;
if (val > max)
return max;
return val;
}
catch (final NumberFormatException nfx) {
//Find where in the string is the parsing error (so as to return ParseException accordingly).
int i = 0;
for (final int cp: text.codePoints().toArray()) {
if (!Character.isDigit(cp))
throw new ParseException("Not a digit.", i);
++i;
}
//Should not happen:
throw new ParseException("Failed to parse input \"" + text + "\".", 0);
}
}
@Override
public String valueToString(final Object value) throws ParseException {
return Objects.toString(value);
}
}
public static class IntegerFormatterFactory extends AbstractFormatterFactory {
private final int min, max;
public IntegerFormatterFactory(final int min, final int max) {
this.min = min;
this.max = max;
}
@Override
public AbstractFormatter getFormatter(final JFormattedTextField tf) {
if (!(tf.getFormatter() instanceof IntegerFormatter))
return new IntegerFormatter(min, max);
return tf.getFormatter();
}
}
public static void main(final String[] args) {
final SpinnerNumberModel model = new SpinnerNumberModel(0, -10, 10, 1);
final JSpinner spin = new JSpinner(model);
spin.setPreferredSize(new Dimension(100, 25));
((DefaultEditor) spin.getEditor()).getTextField().setFormatterFactory(
new IntegerFormatterFactory((Integer) model.getMinimum(), (Integer) model.getMaximum())
);
final JPanel contents = new JPanel(); //FlowLayout.
contents.add(spin);
contents.add(new JButton("Click me to change focus!"));
final JFrame frame = new JFrame("Spinner out of bounds");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(contents);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
添加回答
举报