2015-08-19 6 views
2

Я хотел бы убедиться, что пользователь вводит действительный IPv4-адрес в текстовом поле JavaFX TextField (от 0.0.0 до 255.255.255.255), но я не могу найти правильные решения.javafx textfield ip address

Я пытался с этим кодом:

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

Но я не могу даже набрать одну цифру ... Это, кажется, работает только с одним входом

ответ

2

Это сложно.

Первое примечание заключается в том, что вы используете change.getText(), что дает добавление или удаление текста; вы хотите проверить полученный текст (т. е. текст после добавления или удаления). Для этого используйте change.getControlNewText().

Например, если текущий текст в текстовом поле "255.2", и пользователь вводит "5", то change.getText() вернется "5", тогда как change.getControlNewText() вернется "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); 
    } 
} 
+0

Спасибо, все отлично! Но я не понимаю, почему он работает с вашим регулярным выражением, а не с моим, даже если я использую getControlNewText() вместо getText() . Мне просто нужно выяснить, как убедиться, что пользователь вводит что-то между двумя точками и, возможно, ноль впереди :) – Phoste

+0

Потому что '' 2 "', '" 25 "', '" 255 "', '" 255. "', '" 255.2 "' и т. д. и т. д. не соответствуют вашему регулярному выражению. Он проверяет каждый раз, когда текст изменяется. –

+0

Отредактированный ответ, чтобы уточнить последний пункт. Пожалуйста, примите ответ правильно, если он ответит на ваш вопрос. –

0

Вы можете вручную проверить номера.

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

Это не элегантный, но он работает.

+0

Да b ut, это не мешает пользователю вводить ничего, кроме цифр. Мне хотелось бы что-то в реальном времени :) – Phoste

+0

ой ... если это так, я не могу вам помочь :) Но вы можете проверить [this] (http://stackoverflow.com/questions/22040845/mask- вопрос-ip-address-when-the-user-into-text-field-java-swing) ... это похоже на подобное. @Phoste – Tawcharowsky

+0

Нет проблем! спасибо за ваше время;) – Phoste