微调控制值

时间:2014-12-11 22:51:11

标签: javafx javafx-8

我在8u40b17使用Spinner。

SpinnerValueFactory svf = new SpinnerValueFactory.IntegerSpinnerValueFactory(0, 100);

Spinner sp = new Spinner();
sp.setValueFactory(svf);
sp.setEditable(true);
sp.setPrefWidth(80);

我注意到当我从键盘输入一些值并且我增加了上限值时,预期的数字不是下一个。而不是这个,它是下一个默认值。我怎么解决这个问题?

例如:如果我有5作为默认值而我输入34,那么按下我希望得到35的上箭头实际上得到6。

3 个答案:

答案 0 :(得分:5)

我对旋转器控件有同样的问题。您的错误已记录在此处:JDK-8094205

这是最后一条评论:

  

Jonathan Giles发表了评论 - 2014年12月15日上午12:59

     

在我的仓库本地修复,本周将推送至8u60回购   打开。现在,文本编辑器输入在递增时提交/   调用递减(尽管该值仍未提交   焦点丢失了。)

     

单元测试:

javafx.scene.control.SpinnerTest.test_rt_39655_decrement()
javafx.scene.control.SpinnerTest.test_rt_39655_increment()

变更集:http://hg.openjdk.java.net/openjfx/8u-dev/rt/rev/89ca7d3f699e

这是我对Autocommit微调器的看法。这个将自动提交工厂将接受的任何东西。

public class SpinnerAutoCommit<T> extends Spinner<T> {

    public SpinnerAutoCommit() {
        super();
        addListenerKeyChange();
    }

    public SpinnerAutoCommit(int min, int max, int initialValue) {
        super(min, max, initialValue);
        addListenerKeyChange();
    }

    public SpinnerAutoCommit(int min, int max, int initialValue, int amountToStepBy) {
        super(min, max, initialValue, amountToStepBy);
        addListenerKeyChange();
    }

    public SpinnerAutoCommit(double min, double max, double initialValue) {
        super(min, max, initialValue);
        addListenerKeyChange();
    }

    public SpinnerAutoCommit(double min, double max, double initialValue, double amountToStepBy) {
        super(min, max, initialValue, amountToStepBy);
        addListenerKeyChange();
    }

    public SpinnerAutoCommit(ObservableList<T> items) {
        super(items);
        addListenerKeyChange();
    }

    public SpinnerAutoCommit(SpinnerValueFactory<T> valueFactory) {
        super(valueFactory);
        addListenerKeyChange();
    }

    private void addListenerKeyChange() {
        getEditor().textProperty().addListener((observable, oldValue, newValue) -> {
            commitEditorText();
        });
    }

    private void commitEditorText() {
        if (!isEditable()) return;
        String text = getEditor().getText();
        SpinnerValueFactory<T> valueFactory = getValueFactory();
        if (valueFactory != null) {
            StringConverter<T> converter = valueFactory.getConverter();
            if (converter != null) {
                T value = converter.fromString(text);
                valueFactory.setValue(value);
            }
        }
    }
}

答案 1 :(得分:3)

按照设计,Spinner控件的文本字段中的更改仅在用户通过操作处理程序按Enter键时才会被提交:

    getEditor().setOnAction(action -> {
        String text = getEditor().getText();
        SpinnerValueFactory<T> valueFactory = getValueFactory();
        if (valueFactory != null) {
            StringConverter<T> converter = valueFactory.getConverter();
            if (converter != null) {
                T value = converter.fromString(text);
                valueFactory.setValue(value);
            }
        }
    });

请注意,如果键入的值无法转换,则会抛出NumberFormatException,并在文本字段中保留错误的值。

我们可以提供我们自己的实现,通过事件过滤器监听其他键,如TAB键,同时,如果发生异常,还原最后一个有效值。

这样的事情:

private final Spinner sp = new Spinner();

@Override
public void start(Stage primaryStage) {
    SpinnerValueFactory svf = new SpinnerValueFactory.IntegerSpinnerValueFactory(0, 100);
    sp.setValueFactory(svf);
    sp.setEditable(true);
    sp.setPrefWidth(80);

    // Commit on TAB
    sp.addEventFilter(KeyEvent.ANY, e->{
        if (sp.isEditable() && e.getCode().equals(KeyCode.TAB)) {
            doCommit();
            e.consume();
        }
    });

    // Override Commit on ENTER
    sp.getEditor().setOnAction(e->{
        if(sp.isEditable()) {
            doCommit();
            e.consume();
        }
    });

    Scene scene = new Scene(new StackPane(sp), 300, 250);

    primaryStage.setScene(scene);
    primaryStage.show();        
}

/*
    Commit new value, checking conversion to integer, 
    restoring old valid value in case of exception
*/
private void doCommit(){
    String text = sp.getEditor().getText();
    SpinnerValueFactory<Integer> valueFactory = sp.getValueFactory();
    if (valueFactory != null) {
        StringConverter<Integer> converter = valueFactory.getConverter();
        if (converter != null) {
            try{
                Integer value = converter.fromString(text);
                valueFactory.setValue(value);
            } catch(NumberFormatException nfe){
                sp.getEditor().setText(converter.toString(valueFactory.getValue()));
            }
        }
    }
}

答案 2 :(得分:1)

这解决了我的问题,但它依赖于Apache Commons Validator来验证微调器中输入的值( org.apache.commons.validator.GenericValidator

valueSpinner.getEditor().textProperty().addListener((observable, oldValue, newValue) -> {
        try {
            if (GenericValidator.isInt(newValue)) {
                valueSpinner.getValueFactory().setValue(Integer.parseInt(newValue));
            }
        } catch (NumberFormatException e) {
            if (GenericValidator.isInt(oldValue)) {
                valueSpinner.getValueFactory().setValue(Integer.parseInt(oldValue));
            }
        }
    });

修改: - 您可以在不使用Apache Commons Validator的情况下验证该值,如下例所示: -

    private boolean isInteger(String value) {
        if (value == null) {
            return false;
        }
        try {
            new Integer(value);
            return true;
        } catch (NumberFormatException e) {
            return false;
        } 
    }


    valueSpinner.getEditor().textProperty().addListener((observable, oldValue, newValue) -> {
        try {
            if (isInteger(newValue)) {
                valueSpinner.getValueFactory().setValue(Integer.parseInt(newValue));
            }
        } catch (NumberFormatException e) {
            if (isInteger(oldValue)) {
                valueSpinner.getValueFactory().setValue(Integer.parseInt(oldValue));
            }
        }
    });