【问题标题】:javafx textfield ip addressjavafx 文本字段 IP 地址
【发布时间】:2015-11-12 16:21:57
【问题描述】:

我想确保用户在 JavaFX 文本字段中输入有效的 IPv4 地址(0.0.0.0 到 255.255.255.255),但我似乎找不到任何有效的解决方案。

我用那个代码试过了:

    private final TextField serverURI = new TextField();
    final UnaryOperator<TextFormatter.Change> urlFilter = new UnaryOperator<TextFormatter.Change>() {
        @Override
        public TextFormatter.Change apply(TextFormatter.Change change) {
            final String text = change.getText();
            return (text.isEmpty() || text.matches("^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?).(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?).(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?).(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$")) ? change : null;
        }
    };
    final TextFormatter<String> urlFormatter = new TextFormatter(urlFilter);
    serverURI.setTextFormatter(urlFormatter);

但我什至不能输入一个数字......它似乎只适用于一个输入

【问题讨论】:

    标签: java javafx ip textfield ipv4


    【解决方案1】:

    这些很棘手。

    第一个注释是您正在使用change.getText(),它给出了正在添加或删除的文本;您想测试生成的文本(即添加或删除后的文本)。为此,请使用change.getControlNewText()

    例如,如果文本字段中的当前文本是"255.2",并且用户键入"5",则change.getText() 将返回"5",而change.getControlNewText() 将返回"255.25"

    这仍然留下了主要问题,即过滤器正在应用于文本的每个单独更改,并且您正在测试完整的 IP 地址。因此,例如,要输入“255.255.255.255”,用户将首先输入“2”。如果“2”与您的正则表达式匹配,您测试(即使使用change.getControlNewText()),它会失败(因为它不是完整的 IP 地址),因此更改被否决。在下一个键入的键上,change.getControlNewText() 将是 "25",依此类推。因此,您希望整个序列"2"、"25""255""255.""255.2" 等通过您的过滤器。您还需要过滤器接受用户删除字符、复制和粘贴,等等。

    所以你真的需要一个正则表达式来测试部分条目,而不是完整的条目,这当然有点棘手。以下是一个示例,并非旨在防弹,但应该让您走上正确的轨道(至少)。请注意,您可能需要在用户提交值时进行额外验证,以检查您是否拥有完整、有效的 IP 地址。

    import java.util.function.UnaryOperator;
    
    import javafx.application.Application;
    import javafx.scene.Scene;
    import javafx.scene.control.TextField;
    import javafx.scene.control.TextFormatter;
    import javafx.scene.control.TextFormatter.Change;
    import javafx.scene.layout.StackPane;
    import javafx.stage.Stage;
    
    public class IPTextFieldTest extends Application {
    
        @Override
        public void start(Stage primaryStage) {
            TextField ipTextField = new TextField();
            String regex = makePartialIPRegex();
            final UnaryOperator<Change> ipAddressFilter = c -> {
                String text = c.getControlNewText();
                if  (text.matches(regex)) {
                    return c ;
                } else {
                    return null ;
                }
            };
            ipTextField.setTextFormatter(new TextFormatter<>(ipAddressFilter));
            StackPane root = new StackPane(ipTextField);
            Scene scene = new Scene(root, 350, 120);
            primaryStage.setScene(scene);
            primaryStage.show();
        }
    
        private String makePartialIPRegex() {
            String partialBlock = "(([01]?[0-9]{0,2})|(2[0-4][0-9])|(25[0-5]))" ;
            String subsequentPartialBlock = "(\\."+partialBlock+")" ;
            String ipAddress = partialBlock+"?"+subsequentPartialBlock+"{0,3}";
            return "^"+ipAddress ;
        }
    
    
        public static void main(String[] args) {
            launch(args);
        }
    }
    

    【讨论】:

    • 谢谢,它工作正常!但我不明白为什么它适用于你的正则表达式而不是我的,即使我使用 getControlNewText() 而不是 getText() 我只需要弄清楚如何确保用户在两个点之间输入一些内容,并可能防止输入零在前面:)
    • 因为"2""25""255""255.""255.2" 等与您的正则表达式不匹配。每次文本更改时都会进行检查。
    • 已编辑答案以澄清最后一点。如果它回答了您的问题,请接受正确的答案。
    • 最后一点:我不会试图避免前导零。例如,如果用户不小心输入了200 而不是100,并且您不允许在任何块中使用00,这会使他们难以编辑它。
    • 如果只输入一个点就会返回true。
    【解决方案2】:

    您可以手动检查数字。

    private static boolean checkIfValidIpv4(String text){
       StringTokenizer st = new StringTokenizer(text,".");
       for(int i = 0; i < 4; i++){ 
         if(!st.hasMoreTokens()){
           return false;
         }
         int num = Integer.parseInt(st.nextToken());
         if(num < 0 || num > 255){
           return false;
        }
       }
       if(st.hasMoreTokens()){
         return false;
       }
       return true;
    }
    

    它并不优雅,但它确实有效。

    【讨论】:

    • 是的,但它不会阻止用户输入除数字以外的任何内容。我想要实时的东西:)
    • 哦...如果是这样的话,我帮不了你:)但是你可以检查this问题...它有点相似。 @Phoste
    猜你喜欢
    • 1970-01-01
    • 2017-09-26
    • 2016-11-21
    • 1970-01-01
    • 2015-01-16
    • 2011-10-11
    • 2012-07-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多