当前位置: 首页 > 知识库问答 >
问题:

使用TextFormatter和/或UnaryOperator在JavaFX8中用于整数的数值TextField

步博涉
2023-03-14
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()));  

IntegerStringConverter方法工作得更好:不接受所有像“-16-123”这样的无效数字,而像“0123”这样的数字被转换为“123”。但是只有当文本被提交(通过按enter键)或TextField失去焦点时,才会发生转换。

是否有一种方法可以在每次更新TextField的值时用IntegerStringConverter强制转换第二个方法?

共有1个答案

公孙弘深
2023-03-14

转换器不同于过滤器:转换器指定如何将文本转换为值,过滤器过滤用户可能进行的更改。在这里,听起来两者都想要,但您希望筛选器更准确地筛选允许的更改。

我通常发现,如果更改被接受,检查文本的新值是最容易的。您可以选择一个-,后跟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));
UnaryOperator<Change> integerFilter = change -> {
    String newText = change.getControlNewText();
    // if proposed change results in a valid value, return change as-is:
    if (newText.matches("-?([1-9][0-9]*)?")) { 
        return change;
    } else if ("-".equals(change.getText()) ) {

        // if user types or pastes a "-" in middle of current text,
        // toggle sign of value:

        if (change.getControlText().startsWith("-")) {
            // if we currently start with a "-", remove first character:
            change.setText("");
            change.setRange(0, 1);
            // since we're deleting a character instead of adding one,
            // the caret position needs to move back one, instead of 
            // moving forward one, so we modify the proposed change to
            // move the caret two places earlier than the proposed change:
            change.setCaretPosition(change.getCaretPosition()-2);
            change.setAnchor(change.getAnchor()-2);
        } else {
            // otherwise just insert at the beginning of the text:
            change.setRange(0, 0);
        }
        return change ;
    }
    // invalid change, veto it by returning null:
    return null;
};
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);
    }
}
 类似资料:
  • 问题内容: 我正在尝试通过使用JavaFX 8的TextFormatter为整数创建数字TextField。 UnaryOperator的解决方案: 使用IntegerStringConverter的解决方案: 两种解决方案都有其自身的问题。使用UnaryOperator,我只能按预期输入0到9之间的数字,但是我还需要输入负数,例如“ -512”,其中仅在第一个位置允许使用符号。我也不希望像“ 0

  • 在实体类中使用namedQuery时出错 方法调用namedQuery java.lang.IllegalArgumentExcture:您试图设置类型类的值java.lang.字符串的参数值与预期类型的类java.lang.整数从查询字符串SELECT c从分类c WHEREc.id喜欢:值。 但当使用这种方法时,工作不会出错。 我在JPA中使用eclipselink 2.6

  • 上述情况导致 上述条件返回。 为什么会这样?这些片段之间有什么区别?

  • 问题内容: public class Test { 在第二个输出中,我认为整数范围已过,但是为什么要给出数字,它需要给我一个错误,这种行为的原因是什么? 提前致谢… 问题答案: 您溢出了32位整数的大小。 考虑当我等于10时会发生什么: 但是可以存储在32位整数中的最大正数仅为20亿左右(2个带有9个零)。 实际上,情况变得更糟!中间计算将以有限的精度执行,并且一旦10 * 10 * 10 * 1

  • 我是编程新手,目前使用JavaFX作为个人组织工具。我在这里展示了一个按钮(称为book)和阶段(称为bookStages)的数组列表,一个名为addBook的VBox,以及一个名为bookButtonCount的Int设置为0。 第一个按钮将“书籍”数组列表中的一个按钮添加到VBox。vbox中的按钮应该从舞台数组列表中打开一个阶段。您应该能够多次触发该按钮,每次向vbox添加一个新按钮并将该按

  • 问题内容: 我想使用排球库发布布尔值,双精度数据。我不知道如何使用它。还有其他任何过程吗?谢谢。 这是我的方法。 问题答案: