JavaFX에서 숫자 TextField를 만드는 데 권장되는 방법은 무엇입니까?


85

TextField에 대한 입력을 정수로 제한해야합니다. 어떤 충고?


3
참고 : textProperty를 듣는 것은 잘못되었습니다 ! 이것은 TextFormatter를 사용하기 전에 할 수있는 최선의 방법이었습니다 (fx8u40 정도 이후). 그 이후로 기본 규칙이 적용됩니다. 일반적으로이 메서드에서 관찰 된 값을 수정하는 것은 나쁜 습관으로 간주 되며 TextFormatter를 사용하는 것이 유일한 해결책입니다.
kleopatra

답변:


118

아주 오래된 스레드이지만 붙여 넣으면 더 깔끔해 보이고 숫자가 아닌 문자를 제거합니다.

// force the field to be numeric only
textField.textProperty().addListener(new ChangeListener<String>() {
    @Override
    public void changed(ObservableValue<? extends String> observable, String oldValue, 
        String newValue) {
        if (!newValue.matches("\\d*")) {
            textField.setText(newValue.replaceAll("[^\\d]", ""));
        }
    }
});

3
훌륭하게 작동합니다. 당신은 또한 사용할 수 있습니다 \\D+(또는 \\D) 대신에 [^\\d], 당신은 몇 가지 문자를 저장하려는 경우.
ricky3350

5
더 간단한 방법은 텍스트를 oldValue로 다시 설정하는 것입니다. 이렇게하면 정규식 교체를 엉망으로 만들 필요가 없습니다 (불행히도 전혀 작동하지 않았습니다).
geisterfurz007

@ geisterfurz007 이것은 붙여 넣은 텍스트에서 숫자가 아닌 것을 제거하는 옵션을 제공합니다.
Evan Knowles

10
오래되었습니다. 아래 TextFormatter 답변을 참조하십시오.
gerardw

3
또한 그냥 사용 Integer.parseInt(newValue)하고 사용 try하고 catch오류를 발견 할 수 있습니다 .NumberFormatException
Pixel

43

2016 년 4 월 업데이트

이 답변은 몇 년 전에 생성되었으며 원래 답변은 현재 거의 쓸모가 없습니다.

Java 8u40부터 Java에는 일반적으로 JavaFX TextFields에 숫자와 같은 특정 형식의 입력을 적용하는 데 가장 적합한 TextFormatter 가 있습니다.

TextFormatter를 구체적으로 언급하는이 질문에 대한 다른 답변도 참조하십시오.


원래 답변

요점 에는 이에 대한 몇 가지 예가 있습니다. 아래 예 중 하나를 복제했습니다.

// helper text field subclass which restricts text input to a given range of natural int numbers
// and exposes the current numeric int value of the edit box as a value property.
class IntField extends TextField {
  final private IntegerProperty value;
  final private int minValue;
  final private int maxValue;

  // expose an integer value property for the text field.
  public int  getValue()                 { return value.getValue(); }
  public void setValue(int newValue)     { value.setValue(newValue); }
  public IntegerProperty valueProperty() { return value; }

  IntField(int minValue, int maxValue, int initialValue) {
    if (minValue > maxValue) 
      throw new IllegalArgumentException(
        "IntField min value " + minValue + " greater than max value " + maxValue
      );
    if (maxValue < minValue) 
      throw new IllegalArgumentException(
        "IntField max value " + minValue + " less than min value " + maxValue
      );
    if (!((minValue <= initialValue) && (initialValue <= maxValue))) 
      throw new IllegalArgumentException(
        "IntField initialValue " + initialValue + " not between " + minValue + " and " + maxValue
      );

    // initialize the field values.
    this.minValue = minValue;
    this.maxValue = maxValue;
    value = new SimpleIntegerProperty(initialValue);
    setText(initialValue + "");

    final IntField intField = this;

    // make sure the value property is clamped to the required range
    // and update the field's text to be in sync with the value.
    value.addListener(new ChangeListener<Number>() {
      @Override public void changed(ObservableValue<? extends Number> observableValue, Number oldValue, Number newValue) {
        if (newValue == null) {
          intField.setText("");
        } else {
          if (newValue.intValue() < intField.minValue) {
            value.setValue(intField.minValue);
            return;
          }

          if (newValue.intValue() > intField.maxValue) {
            value.setValue(intField.maxValue);
            return;
          }

          if (newValue.intValue() == 0 && (textProperty().get() == null || "".equals(textProperty().get()))) {
            // no action required, text property is already blank, we don't need to set it to 0.
          } else {
            intField.setText(newValue.toString());
          }
        }
      }
    });

    // restrict key input to numerals.
    this.addEventFilter(KeyEvent.KEY_TYPED, new EventHandler<KeyEvent>() {
      @Override public void handle(KeyEvent keyEvent) {
        if(intField.minValue<0) {
                if (!"-0123456789".contains(keyEvent.getCharacter())) {
                    keyEvent.consume();
                }
            }
            else {
                if (!"0123456789".contains(keyEvent.getCharacter())) {
                    keyEvent.consume();
                }
            }
      }
    });

    // ensure any entered values lie inside the required range.
    this.textProperty().addListener(new ChangeListener<String>() {
      @Override public void changed(ObservableValue<? extends String> observableValue, String oldValue, String newValue) {
        if (newValue == null || "".equals(newValue) || (intField.minValue<0 && "-".equals(newValue))) {
          value.setValue(0);
          return;
        }

        final int intValue = Integer.parseInt(newValue);

        if (intField.minValue > intValue || intValue > intField.maxValue) {
          textProperty().setValue(oldValue);
        }

        value.set(Integer.parseInt(textProperty().get()));
      }
    });
  }
}

41

나는 이것이 다소 오래된 스레드라는 것을 알고 있지만 미래의 독자를 위해 여기에 매우 직관적 인 또 다른 솔루션이 있습니다.

public class NumberTextField extends TextField
{

    @Override
    public void replaceText(int start, int end, String text)
    {
        if (validate(text))
        {
            super.replaceText(start, end, text);
        }
    }

    @Override
    public void replaceSelection(String text)
    {
        if (validate(text))
        {
            super.replaceSelection(text);
        }
    }

    private boolean validate(String text)
    {
        return text.matches("[0-9]*");
    }
}

편집 : 개선 제안에 대해 none_SCBoy 에게 감사드립니다 .


1
누구든지 십진수 (예 : 123.456)에 사용할 정규식을 알고 있습니까? validate (text) 함수 매개 변수 "text"의 값은 텍스트 필드의 전체 문자열이 아니라 사용자가 마지막으로 편집 한 문자이므로 정규식이 올바르게 일치하지 않을 수 있습니다. 예를 들어 다음 text.matches("\\d+");
mils


1
좋은 해결책이라고 생각하지만 한 가지만 바꾸겠습니다. text.matches ( "[0-9] *")를 작성하는 대신 패턴에 대한 변수를 만들고 컴파일합니다. 코드 패턴은 누군가 필드에 문자를 쓸 때마다 컴파일되며 이는 CPU와 메모리 비용이 많이 듭니다. 그래서 변수를 추가합니다 : private static Pattern integerPattern = Pattern.compile ( "[0-9] *"); 그리고 유효성 검사 본문을 다음으로 대체하십시오.
P. Jowko

38

JavaFX 8u40부터 텍스트 필드에 TextFormatter 객체를 설정할 수 있습니다.

UnaryOperator<Change> filter = change -> {
    String text = change.getText();

    if (text.matches("[0-9]*")) {
        return change;
    }

    return null;
};
TextFormatter<String> textFormatter = new TextFormatter<>(filter);
fieldNport = new TextField();
fieldNport.setTextFormatter(textFormatter);

이렇게하면 text 속성에 변경 리스너를 추가하고 해당 리스너에서 텍스트를 수정할 때 발생하는 하위 클래스 지정 및 중복 변경 이벤트를 모두 방지 할 수 있습니다.


30

TextInputA가 들어TextFormatter 포맷으로 변환하는 데 사용하고, 입력 할 수있는 텍스트의 유형을 제한 할 수있다.

그만큼 TextFormatter 입력을 거부하기 위해 사용될 수있는 필터를 갖는다. 유효한 정수가 아닌 것은 거부하도록 설정해야합니다. 또한 문자열 값을 나중에 바인딩 할 수있는 정수 값으로 변환하기 위해 설정해야하는 변환기가 있습니다.

재사용 가능한 필터를 만들 수 있습니다.

public class IntegerFilter implements UnaryOperator<TextFormatter.Change> {
    private final static Pattern DIGIT_PATTERN = Pattern.compile("\\d*");

    @Override
    public Change apply(TextFormatter.Change aT) {
        return DIGIT_PATTERN.matcher(aT.getText()).matches() ? aT : null;
    }
}

필터는 세 가지 작업 중 하나를 수행 할 수 있습니다. 변경 사항을 수정하지 않은 상태로 반환하여 그대로 받아 들일 수 있으며, 적합하다고 간주되는 방식으로 변경 사항을 변경할 수 있거나 반환 할 수 있습니다. null 변경 사항을 모두 함께 거부하기 위해 .

우리는 표준을 사용할 것입니다 IntegerStringConverter 을 변환기로 .

종합하면 다음과 같습니다.

TextField textField = ...;

TextFormatter<Integer> formatter = new TextFormatter<>(
    new IntegerStringConverter(), // Standard converter form JavaFX
    defaultValue, 
    new IntegerFilter());
formatter.valueProperty().bindBidirectional(myIntegerProperty);

textField.setTextFormatter(formatter);

재사용 가능한 필터가 필요하지 않다면이 멋진 한 줄을 대신 사용할 수 있습니다.

TextFormatter<Integer> formatter = new TextFormatter<>(
    new IntegerStringConverter(), 
    defaultValue,  
    c -> Pattern.matches("\\d*", c.getText()) ? c : null );

21

나는 예외를 좋아하지 않아서 matchesString-Class 의 함수를 사용했습니다.

text.textProperty().addListener(new ChangeListener<String>() {
    @Override
    public void changed(ObservableValue<? extends String> observable, String oldValue, 
        String newValue) {
        if (newValue.matches("\\d*")) {
            int value = Integer.parseInt(newValue);
        } else {
            text.setText(oldValue);
        }
    }
});

1
수가 너무 클 수 있기 때문에 때때로 예외가 있습니다.
schlagi123

1
팁 : 정규식 "\\ d +"를 "\\ d *"로 바꿉니다. 이렇게하면 텍스트 입력 필드에서 모든 문자를 제거 할 수 있습니다 (필드를 지우려면 백 스페이스 / 삭제 사용).
Guus

1
캐럿 위치를 이전 값으로 다시 설정 한 후 설정하는 것을 잊지 마십시오.textField.positionCaret(textField.getLength());
hsson

if (newValue.matches("\\d*") && newValue.getText().length < 5) 이 경우 입력을 4 자리로 제한하려면 첫 번째 조건을 :으로 변경하십시오 .
Cappuccino90

@ Cappuccino90 정규식을 구문 분석하는 것보다 길이 검사가 각 히트에 대해 훨씬 저렴하기 때문에 문을 전환해야합니다.
thatsIch

9

Java SE 8u40 부터 이러한 요구에 대해 " 정수 "를Spinner 를 사용하여 키보드의 위쪽 화살표 / 아래쪽 화살표 키 또는 위쪽 화살표 / 아래쪽 화살표 제공 버튼을 사용하여 유효한 정수를 안전하게 선택할 수 있습니다.

min , a max를 정의 할 수도 있습니다.초기 값을 하여 허용되는 값과 단계 당 증가 또는 감소 할 양을 제한 .

예를 들면

// Creates an integer spinner with 1 as min, 10 as max and 2 as initial value
Spinner<Integer> spinner1 = new Spinner<>(1, 10, 2);
// Creates an integer spinner with 0 as min, 100 as max and 10 as initial 
// value and 10 as amount to increment or decrement by, per step
Spinner<Integer> spinner2 = new Spinner<>(0, 100, 10, 10);

" integer "스피너와 " double "스피너 가있는 결과의 예

여기에 이미지 설명 입력

스피너 사용자는 값들의 순서화 된 시퀀스에서 다수의 또는 객체를 선택할 수 있도록 한 줄의 텍스트 필드 제어이다. 스피너는 일반적으로 시퀀스 요소를 단계별로 이동할 수있는 한 쌍의 작은 화살표 버튼을 제공합니다. 키보드의 위쪽 화살표 / 아래쪽 화살표 키도 요소를 순환합니다. 사용자는 스피너에 직접 (법적) 값을 입력 할 수도 있습니다. 콤보 상자가 유사한 기능을 제공하지만 스피너는 중요한 데이터를 가릴 수있는 드롭 다운 목록이 필요하지 않고 최대 값에서 최소값으로 다시 래핑하는 등의 기능을 허용하기 때문에 선호되는 경우가 있습니다 (예 : 가장 큰 양의 정수에서 0까지).

Spinner 컨트롤 에 대한 자세한 정보


사람들은 스피너가 텍스트 입력이나 초점 손실에 대해 유효성을 검사하지 않아야합니다
geometrikal

7

Java 1.8 Lambda를 사용하는 경우 선호하는 대답은 더 작을 수 있습니다.

textfield.textProperty().addListener((observable, oldValue, newValue) -> {
    if (newValue.matches("\\d*")) return;
    textfield.setText(newValue.replaceAll("[^\\d]", ""));
});

6
TextField text = new TextField();

text.textProperty().addListener(new ChangeListener<String>() {
    @Override
    public void changed(ObservableValue<? extends String> observable,
            String oldValue, String newValue) {
        try {
            Integer.parseInt(newValue);
            if (newValue.endsWith("f") || newValue.endsWith("d")) {
                manualPriceInput.setText(newValue.substring(0, newValue.length()-1));
            }
        } catch (ParseException e) {
            text.setText(oldValue);
        }
    }
});

if절은 Int.parseInt ()에 의해 올바르게 구문 분석 된 0.5d 또는 0.7f와 같은 입력을 처리하는 데 중요하지만 텍스트 필드에는 나타나지 않아야합니다.


9
어? 언제 0.5d가 Integer.parseInt ()에 의해 올바르게 구문 분석 되었습니까?! java.lang.NumberFormatException : 입력 문자열의 경우 : "0.5d"(정수가 아니기 때문에 예상대로)
Burkhard

4

이 간단한 코드를 시도해보십시오.

DecimalFormat format = new DecimalFormat( "#.0" );
TextField field = new TextField();
field.setTextFormatter( new TextFormatter<>(c ->
{
    if ( c.getControlNewText().isEmpty() )
    {
        return c;
    }

    ParsePosition parsePosition = new ParsePosition( 0 );
    Object object = format.parse( c.getControlNewText(), parsePosition );

    if ( object == null || parsePosition.getIndex() <          c.getControlNewText().length() )
    {
        return null;
    }
    else
    {
        return c;
    }
}));

3

둘 이상의 TextField에 동일한 리스너를 적용하려는 경우 여기에 가장 간단한 솔루션이 있습니다.

TextField txtMinPrice, txtMaxPrice = new TextField();

ChangeListener<String> forceNumberListener = (observable, oldValue, newValue) -> {
    if (!newValue.matches("\\d*"))
      ((StringProperty) observable).set(oldValue);
};

txtMinPrice.textProperty().addListener(forceNumberListener);
txtMaxPrice.textProperty().addListener(forceNumberListener);

3

이것은 나를 위해 일했습니다.

public void RestrictNumbersOnly(TextField tf){
    tf.textProperty().addListener(new ChangeListener<String>() {
        @Override
        public void changed(ObservableValue<? extends String> observable, String oldValue, 
            String newValue) {
            if (!newValue.matches("|[-\\+]?|[-\\+]?\\d+\\.?|[-\\+]?\\d+\\.?\\d+")){
                tf.setText(oldValue);
            }
        }
    });
}

3

Evan Knowles 답변 TextFormatter을 JavaFX 8의 답변과 결합하여 내 아이디어를 돕고 싶습니다.

textField.setTextFormatter(new TextFormatter<>(c -> {
    if (!c.getControlNewText().matches("\\d*")) 
        return null;
    else
        return c;
    }
));

행운을 빕니다;) 침착하고 자바 코드를 작성하십시오


2

다음은 JavaFX 8u40에 도입 된을 TextField사용하여 에서 몇 가지 기본 유효성 검사를 처리하는 간단한 클래스입니다.TextFormatter

편집하다:

(Floern의 의견에 대한 코드 추가)

import java.text.DecimalFormatSymbols;
import java.util.regex.Pattern;

import javafx.beans.NamedArg;
import javafx.scene.control.TextFormatter;
import javafx.scene.control.TextFormatter.Change;

public class TextFieldValidator {

    private static final String CURRENCY_SYMBOL   = DecimalFormatSymbols.getInstance().getCurrencySymbol();
    private static final char   DECIMAL_SEPARATOR = DecimalFormatSymbols.getInstance().getDecimalSeparator();

    private final Pattern       INPUT_PATTERN;

    public TextFieldValidator(@NamedArg("modus") ValidationModus modus, @NamedArg("countOf") int countOf) {
        this(modus.createPattern(countOf));
    }

    public TextFieldValidator(@NamedArg("regex") String regex) {
        this(Pattern.compile(regex));
    }

    public TextFieldValidator(Pattern inputPattern) {
        INPUT_PATTERN = inputPattern;
    }

    public static TextFieldValidator maxFractionDigits(int countOf) {
        return new TextFieldValidator(maxFractionPattern(countOf));
    }

    public static TextFieldValidator maxIntegers(int countOf) {
        return new TextFieldValidator(maxIntegerPattern(countOf));
    }

    public static TextFieldValidator integersOnly() {
        return new TextFieldValidator(integersOnlyPattern());
    }

    public TextFormatter<Object> getFormatter() {
        return new TextFormatter<>(this::validateChange);
    }

    private Change validateChange(Change c) {
        if (validate(c.getControlNewText())) {
            return c;
        }
        return null;
    }

    public boolean validate(String input) {
        return INPUT_PATTERN.matcher(input).matches();
    }

    private static Pattern maxFractionPattern(int countOf) {
        return Pattern.compile("\\d*(\\" + DECIMAL_SEPARATOR + "\\d{0," + countOf + "})?");
    }

    private static Pattern maxCurrencyFractionPattern(int countOf) {
        return Pattern.compile("^\\" + CURRENCY_SYMBOL + "?\\s?\\d*(\\" + DECIMAL_SEPARATOR + "\\d{0," + countOf + "})?\\s?\\" +
                CURRENCY_SYMBOL + "?");
    }

    private static Pattern maxIntegerPattern(int countOf) {
        return Pattern.compile("\\d{0," + countOf + "}");
    }

    private static Pattern integersOnlyPattern() {
        return Pattern.compile("\\d*");
    }

    public enum ValidationModus {

        MAX_CURRENCY_FRACTION_DIGITS {
            @Override
            public Pattern createPattern(int countOf) {
                return maxCurrencyFractionPattern(countOf);
            }
        },

        MAX_FRACTION_DIGITS {
            @Override
            public Pattern createPattern(int countOf) {
                return maxFractionPattern(countOf);
            }
        },
        MAX_INTEGERS {
            @Override
            public Pattern createPattern(int countOf) {
                return maxIntegerPattern(countOf);
            }
        },

        INTEGERS_ONLY {
            @Override
            public Pattern createPattern(int countOf) {
                return integersOnlyPattern();
            }
        };

        public abstract Pattern createPattern(int countOf);
    }

}

다음과 같이 사용할 수 있습니다.

textField.setTextFormatter(new TextFieldValidator(ValidationModus.INTEGERS_ONLY).getFormatter());

또는 fxml 파일에서 인스턴스화하고 해당 속성을 사용하여 customTextField에 적용 할 수 있습니다.

app.fxml :

<fx:define>
    <TextFieldValidator fx:id="validator" modus="INTEGERS_ONLY"/>
</fx:define>

CustomTextField.class :

public class CustomTextField {

private TextField textField;

public CustomTextField(@NamedArg("validator") TextFieldValidator validator) {
        this();
        textField.setTextFormatter(validator.getFormatter());
    }
}

github의 코드


2

이것이 내가 사용하는 것입니다.

private TextField textField;
textField.textProperty().addListener(new ChangeListener<String>() {
    @Override
    public void changed(ObservableValue<? extends String> observable, String oldValue, String newValue) {
        if(!newValue.matches("[0-9]*")){
            textField.setText(oldValue);
        }

    }
});

람다 표기법에서는 다음과 같습니다.

private TextField textField;
textField.textProperty().addListener((observable, oldValue, newValue) -> {
    if(!newValue.matches("[0-9]*")){
        textField.setText(oldValue);
    }
});

2

이 메서드를 사용하면 TextField가 모든 처리를 완료 할 수 있습니다 (복사 / 붙여 넣기 / 안전 취소). 클래스를 확장 할 필요가 없으며 변경할 때마다 새 텍스트로 수행 할 작업을 결정할 수 있습니다 (논리로 푸시하거나 이전 값으로 되돌 리거나 수정하기 위해).

  // fired by every text property change
textField.textProperty().addListener(
  (observable, oldValue, newValue) -> {
    // Your validation rules, anything you like
      // (! note 1 !) make sure that empty string (newValue.equals("")) 
      //   or initial text is always valid
      //   to prevent inifinity cycle
    // do whatever you want with newValue

    // If newValue is not valid for your rules
    ((StringProperty)observable).setValue(oldValue);
      // (! note 2 !) do not bind textProperty (textProperty().bind(someProperty))
      //   to anything in your code.  TextProperty implementation
      //   of StringProperty in TextFieldControl
      //   will throw RuntimeException in this case on setValue(string) call.
      //   Or catch and handle this exception.

    // If you want to change something in text
      // When it is valid for you with some changes that can be automated.
      // For example change it to upper case
    ((StringProperty)observable).setValue(newValue.toUpperCase());
  }
);

귀하의 경우에는이 논리를 내부에 추가하십시오. 완벽하게 작동합니다.

   if (newValue.equals("")) return; 
   try {
     Integer i = Integer.valueOf(newValue);
     // do what you want with this i
   } catch (Exception e) {
     ((StringProperty)observable).setValue(oldValue);
   }

0

음. 몇 주 전에 그 문제가 발생했습니다. API는이를 달성하기위한 제어 기능을 제공하지 않으므로 자체 제어
를 사용할 수 있습니다.
나는 다음과 같은 것을 사용했다.

public class IntegerBox extends TextBox {
    public-init var value : Integer = 0;
    protected function apply() {
        try {
            value = Integer.parseInt(text);
        } catch (e : NumberFormatException) {}
        text = "{value}";
    }
    override var focused = false on replace {apply()};
    override var action = function () {apply()}
}

그것은 정상이 같은 방법으로 사용되는 TextBox,
뿐만 아니라이 value입력 된 정수를 저장하는 속성을.
컨트롤이 포커스를 잃으면 값의 유효성을 검사 하고 값을 되돌립니다 (유효하지 않은 경우).


2
이것이 무슨 언어 지?
Stealth Rabbi

그것은의 자바 FX 스크립트 랍비, 그건 쓸모 .
jewelsea 2016-04-05

0

이 코드는 당신의 textField를 숫자로만 받아들이십시오

textField.lengthProperty().addListener((observable, oldValue, newValue) -> {
        if(newValue.intValue() > oldValue.intValue()){
            char c = textField.getText().charAt(oldValue.intValue());
            /** Check if the new character is the number or other's */
            if( c > '9' || c < '0'){
                /** if it's not number then just setText to previous one */
                textField.setText(textField.getText().substring(0,textField.getText().length()-1));
            }
        }
    });

0

이 코드는 복사 / 붙여 넣기를 시도하더라도 잘 작동합니다.

myTextField.textProperty().addListener((observable, oldValue, newValue) -> {
    if (!newValue.matches("\\d*")) {
        myTextField.setText(oldValue);

    }
});

-1

JavaFX의 최근 업데이트에서는 다음과 같이 Platform.runLater 메서드에 새 텍스트를 설정해야합니다.

    private void set_normal_number(TextField textField, String oldValue, String newValue) {
    try {
        int p = textField.getCaretPosition();
        if (!newValue.matches("\\d*")) {
            Platform.runLater(() -> {
                textField.setText(newValue.replaceAll("[^\\d]", ""));
                textField.positionCaret(p);
            });
        }
    } catch (Exception e) {
    }
}

캐럿 위치도 설정하는 것이 좋습니다.


1
답변 주셔서 감사합니다! 왜 Platform.runLater필요한지 조금 설명해 주 시겠습니까?
TuringTux

@TuringTux는 JavaFX의 최신 버전에서 Platform.runLater를 사용하지 않으면 예외가 발생합니다.
bdshahab

-1

Evan Knowles 답변을 개선하고 싶습니다 : https://stackoverflow.com/a/30796829/2628125

제 경우에는 UI 구성 요소 부분에 대한 핸들러가있는 클래스가 있습니다. 초기화 :

this.dataText.textProperty().addListener((observable, oldValue, newValue) -> this.numericSanitization(observable, oldValue, newValue));

그리고 numbericSanitization 방법 :

private synchronized void numericSanitization(ObservableValue<? extends String> observable, String oldValue, String newValue) {
    final String allowedPattern = "\\d*";

    if (!newValue.matches(allowedPattern)) {
        this.dataText.setText(oldValue);
    }
}

동기화 된 키워드이전 실행이 완료되기 전에 setText가 호출되는 경우 javafx에서 발생할 수있는 렌더링 잠금 문제를 방지하기 위해 가 추가되었습니다. 잘못된 문자를 정말 빠르게 입력하기 시작하면 재현하기 쉽습니다.

또 다른 장점은 일치시킬 패턴을 하나만 유지하고 롤백 만한다는 것입니다. 다른 살균 패턴에 대한 솔루션을 쉽게 제거 할 수 있기 때문에 더 좋습니다.


-1
rate_text.textProperty().addListener(new ChangeListener<String>() {

    @Override
    public void changed(ObservableValue<? extends String> observable, String oldValue, String newValue) {
        String s="";
        for(char c : newValue.toCharArray()){
            if(((int)c >= 48 && (int)c <= 57 || (int)c == 46)){
                s+=c;
            }
        }
        rate_text.setText(s);
    }
});

정수 값과 10 진수 값 (ASCII 코드 46 포함) 만 입력 할 수 있으므로 제대로 작동합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.