带TextFormatter和/或UnaryOperator的JavaFX 8中整数的数字文本字段

带TextFormatter和/或UnaryOperator的JavaFX 8中整数的数字文本字段,java,javafx,textfield,numeric,formatter,Java,Javafx,Textfield,Numeric,Formatter,我试图使用JavaFX8的TextFormatter为整数创建一个数字TextField 使用UnaryOperator的解决方案: UnaryOperator<Change> integerFilter = change -> { String input = change.getText(); if (input.matches("[0-9]*")) { return change; } return null; }; m

我试图使用JavaFX8的TextFormatter为整数创建一个数字TextField

使用UnaryOperator的解决方案:

UnaryOperator<Change> integerFilter = change -> {
    String input = change.getText();
    if (input.matches("[0-9]*")) { 
        return change;
    }
    return null;
};

myNumericField.setTextFormatter(new TextFormatter<String>(integerFilter));
myNumericField.setTextFormatter(new TextFormatter<>(new IntegerStringConverter()));  
UnaryOperator integerFilter=更改->{
字符串输入=change.getText();
如果(input.matches(“[0-9]*”){
回报变化;
}
返回null;
};
setTextFormatter(新的TextFormatter(integerFilter));
使用IntegerStringConverter的解决方案:

UnaryOperator<Change> integerFilter = change -> {
    String input = change.getText();
    if (input.matches("[0-9]*")) { 
        return change;
    }
    return null;
};

myNumericField.setTextFormatter(new TextFormatter<String>(integerFilter));
myNumericField.setTextFormatter(new TextFormatter<>(new IntegerStringConverter()));  
myNumericField.setTextFormatter(新的TextFormatter(新的IntegerStringConverter());
两种解决方案都有各自的问题。使用UnaryOperator,我只能像预期的那样输入0到9之间的数字,但我还需要输入负数,如“-512”,其中符号只允许在第一个位置。此外,我不希望像“00016”这样的数字仍然是可能的

IntegerStringConverter方法工作得更好:像“-16-123”这样的每个无效数字都不被接受,像“0123”这样的数字被转换为“123”。但转换仅在提交文本(通过按enter键)或文本字段失去焦点时发生


是否有办法在每次更新文本字段的值时使用IntegerStringConverter强制转换第二个方法?

转换器与筛选器不同:转换器指定如何将文本转换为值,并且筛选器筛选器可由用户更改。这听起来像是两个都需要,但您希望过滤器能够更准确地过滤允许的更改

我通常发现,如果接受了更改,检查文本的新值是最容易的。您希望有一个
-
,后跟
1-9
,后面有任意数字。允许空字符串很重要,否则用户将无法删除所有内容

所以你可能需要像

UnaryOperator<Change> integerFilter = change -> {
    String newText = change.getControlNewText();
    if (newText.matches("-?([1-9][0-9]*)?")) { 
        return change;
    }
    return null;
};

myNumericField.setTextFormatter(
    new TextFormatter<Integer>(new IntegerStringConverter(), 0, integerFilter));
这将允许用户在任意点按
-
,并切换整数的符号

SSCCE:

import java.util.function.UnaryOperator;

import javafx.application.Application;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.TextField;
import javafx.scene.control.TextFormatter;
import javafx.scene.control.TextFormatter.Change;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import javafx.util.StringConverter;
import javafx.util.converter.IntegerStringConverter;

public class IntegerFieldExample extends Application {

    @Override
    public void start(Stage primaryStage) {
        TextField integerField = new TextField();
        UnaryOperator<Change> integerFilter = change -> {
            String newText = change.getControlNewText();
            if (newText.matches("-?([1-9][0-9]*)?")) { 
                return change;
            } else if ("-".equals(change.getText()) ) {
                if (change.getControlText().startsWith("-")) {
                    change.setText("");
                    change.setRange(0, 1);
                    change.setCaretPosition(change.getCaretPosition()-2);
                    change.setAnchor(change.getAnchor()-2);
                    return change ;
                } else {
                    change.setRange(0, 0);
                    return change ;
                }
            }
            return null;
        };

        // modified version of standard converter that evaluates an empty string 
        // as zero instead of null:
        StringConverter<Integer> converter = new IntegerStringConverter() {
            @Override
            public Integer fromString(String s) {
                if (s.isEmpty()) return 0 ;
                return super.fromString(s);
            }
        };

        TextFormatter<Integer> textFormatter = 
                new TextFormatter<Integer>(converter, 0, integerFilter);
        integerField.setTextFormatter(textFormatter);

        // demo listener:
        textFormatter.valueProperty().addListener((obs, oldValue, newValue) -> System.out.println(newValue));

        VBox root = new VBox(5, integerField, new Button("Click Me"));
        root.setAlignment(Pos.CENTER);
        Scene scene = new Scene(root, 300, 120);
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    public static void main(String[] args) {
        launch(args);
    }
}
import java.util.function.UnaryOperator;
导入javafx.application.application;
导入javafx.geometry.Pos;
导入javafx.scene.scene;
导入javafx.scene.control.Button;
导入javafx.scene.control.TextField;
导入javafx.scene.control.TextFormatter;
导入javafx.scene.control.TextFormatter.Change;
导入javafx.scene.layout.VBox;
导入javafx.stage.stage;
导入javafx.util.StringConverter;
导入javafx.util.converter.IntegerStringConverter;
公共类IntegerFieldExample扩展应用程序{
@凌驾
公共无效开始(阶段primaryStage){
TextField integerField=新的TextField();
一元运算符整型过滤器=更改->{
字符串newText=change.getControlNewText();
如果(newText.matches(“-?([1-9][0-9]*)?”){
回报变化;
}else如果(“-”.equals(change.getText())){
if(change.getControlText().startsWith(“-”){
change.setText(“”);
改变设置范围(0,1);
change.setCaretPosition(change.getCaretPosition()-2);
change.setAnchor(change.getAnchor()-2);
回报变化;
}否则{
改变设置范围(0,0);
回报变化;
}
}
返回null;
};
//计算空字符串的标准转换器的修改版本
//作为零而不是空:
StringConverter converter=新整数StringConverter(){
@凌驾
公共整数fromString(字符串s){
如果(s.isEmpty())返回0;
返回super.fromString;
}
};
TextFormatter TextFormatter=
新的文本格式化程序(转换器、0、整数过滤器);
integerField.setTextFormatter(textFormatter);
//演示侦听器:
textFormatter.valueProperty().addListener((obs,oldValue,newValue)->System.out.println(newValue));
VBox root=new VBox(5,integerField,new按钮(“单击我”);
根部设置对齐(位置中心);
场景=新场景(根,300,120);
初级阶段。场景(场景);
primaryStage.show();
}
公共静态void main(字符串[]args){
发射(args);
}
}
TextField txtpoint=new TextField();
txtpoint.textProperty().addListener(新的ChangeListener()){
@凌驾

public void已更改(ObservableValueSmart在数字组上使用
!正在考虑
-?([1-9]?|[1-9][0-9]*)
,但这更干净了!我非常感谢您的努力,您的解决方案工作得非常好!对于堆栈溢出,通常欢迎使用一些解释/使用说明。因为fx8u80这是错误的(您不能更改正在侦听的属性),请改用textFormatter