当前位置: 首页 > 面试题库 >

具有TextFormatter和/或UnaryOperator的JavaFX 8中整数的数字TextField

阎冠玉
2023-03-14
问题内容

我正在尝试通过使用JavaFX 8的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));

使用IntegerStringConverter的解决方案:

myNumericField.setTextFormatter(new TextFormatter<>(new IntegerStringConverter()));

两种解决方案都有其自身的问题。使用UnaryOperator,我只能按预期输入0到9之间的数字,但是我还需要输入负数,例如“
-512”,其中仅在第一个位置允许使用符号。我也不希望像“ 00016”这样的数字仍然可行。

IntegerStringConverter方法的工作方式更好:不接受每个无效数字(例如“ -16-123”),并且将数字(例如“ 0123”)转换为“
123”。但是,仅在提交文本(通过按Enter键)或TextField失去焦点时才发生转换。

每当TextField的值更新时,是否有一种方法可以用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));

您甚至可以向过滤器添加更多功能,以使其-以更智能的方式进行处理,例如

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;
};

这将使用户-可以随时按下它,并且可以切换整数的符号。

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);
    }
}


 类似资料:
  • IntegerStringConverter方法工作得更好:不接受所有像“-16-123”这样的无效数字,而像“0123”这样的数字被转换为“123”。但是只有当文本被提交(通过按enter键)或TextField失去焦点时,才会发生转换。 是否有一种方法可以在每次更新TextField的值时用IntegerStringConverter强制转换第二个方法?

  • 问题内容: 有人可以向我解释为什么以下代码在Java中可以编译吗? 为什么这不等同于以下不编译的内容? Java语言规范(第3.10.1节)指出:“如果整数文字带有ASCII字母L或l(ell)后缀,则为类型;否则为(4.2.1节)。” 第4.2.2节提到“数值运算符,其结果是type 或。” 因此,据我所知,加法的结果应为,不能将其赋给变量。 但是,它可以很好地进行编译(至少在Sun JDK 1

  • 问题内容: 有一些值,例如AB,A012B,CD,1、10、01、9我必须对其进行排序,输出的输出应为01、1、9、10,A012B,AB,CD可以使用任何试图使用collection的collection .sort函数,但将所有内容都视为字符串并像01,1,10,9,A012B,AB,CD一样打印,这不是我的要求…请帮助 问题答案: //捕鱼技术 //不够??? //这是鱼

  • 问题内容: 我有两个值: [3:6] 我试图在Golang中玩一些游戏,但是我找不到能够根据这些值创建数组的好方法。 我要实现的目标是: 问题答案: 您可以利用该构造使其更紧凑甚至更快: 出于好奇,可以在不使用循环变量的情况下实现循环,但是这样会更慢,并且代码也更长。通过递减: 或递增:

  • 问题内容: 我正在尝试查看int是否具有相同数字的倍数。尝试不使用字符串方法或数组。我遇到的主要方法是。当重复数字位于末尾时有效,但当它们位于开始或中间时无效。 } 如果运行此命令,您将看到‘2’重复出现,但该方法仍会评估其应为的时间。 问题答案: 这是一个简短而甜蜜的版本:) 它的工作方式非常简单。是一个整数,用于存储已经遇到的数字(由于十进制系统编号只有10位,而整数给出16位,因此我们有足够

  • 问题内容: 我已经在Stack Overflow上重复了几次这个问题,但是没有一个人充分探讨这个问题(或者至少以一种对我有帮助的方式) 问题在于,数据库查询应在PHP中为整数列返回整数数据类型。而是查询将每一列作为字符串类型返回。 我已经确保“ PDO :: ATTR_STRINGIFY_FETCHES”为 false 只是为了确保结果不会被强制转换为字符串。 我见过的答案: 做不到 不,它可以在