javafx 文本框ip地址

javafx textfield ip address

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

我试过那个代码:

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

但是我什至不能输入一个数字...它似乎只用一个输入就可以工作

您可以手动查看号码。

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

虽然不优雅,但很管用。

这些很棘手。

第一个注意事项是您正在使用 change.getText(),它给出了添加或删除的文本;你想测试结果文本(即添加或删除后的文本)。为此,使用 change.getControlNewText()

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

这仍然存在主要问题,即过滤器应用于文本的每个单独更改,并且您正在测试完整的 IP 地址。因此,例如,要键入“255.255.255.255”,用户将首先键入“2”。您测试(即使使用 change.getControlNewText())如果“2”与您的正则表达式匹配,它会失败(因为它不是完整的 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);
    }
}