JavaFX'te sayısal bir TextField oluşturmanın önerilen yolu nedir?


85

Bir TextField girişini tamsayılarla sınırlamam gerekiyor. Herhangi bir tavsiye?


3
Not: textProperty'yi dinlemek yanlış ! Bir TextFormatter'a sahip olmadan önce yapılabilecek en iyi şey buydu (fx8u40'tan beri). O zamandan beri, temel kural geçerlidir: Genel olarak, bu yöntemde, gözlenen değerini değiştirmek için kötü bir uygulama olarak kabul edilir ve bir ile TextFormatter olan tek olarak kabul edilebilir bir çözelti.
kleopatra

Yanıtlar:


120

Çok eski iş parçacığı, ancak bu daha düzgün görünüyor ve yapıştırıldığında sayısal olmayan karakterleri çıkarıyor.

// 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
Harika çalışıyor. Birkaç karakter kaydetmek istiyorsanız, yerine \\D+(veya sadece \\D) kullanabileceğinizi unutmayın [^\\d].
ricky3350

5
Daha da basit olanı, metni eskiDeğer'e geri döndürmektir. Bu şekilde normal ifade değiştirmeleriyle uğraşmak zorunda kalmazsınız (ne yazık ki benim için hiç işe yaramadı).
geisterfurz007

@ geisterfurz007 Bu, sayısal olmayanları yapıştırılan metinden çıkarma seçeneği sunar.
Evan Knowles

10
Güncel değil, aşağıdaki TextFormatter yanıtına bakın.
gerardw

3
Ayrıca muhtemelen sadece kullanıp Integer.parseInt(newValue)kullanabilir tryve catchbir hatayı tespit edebilirNumberFormatException
Pixel

44

Nisan 2016 Güncellemesi

Bu cevap birkaç yıl önce oluşturuldu ve orijinal cevap büyük ölçüde artık eskimiş durumda.

Java 8u40'tan bu yana, Java , genellikle JavaFX TextFields üzerindeki sayısal gibi belirli biçimlerin girişini zorlamak için en iyi olan bir TextFormatter'a sahiptir:

Ayrıca, özellikle TextFormatter'dan bahseden bu sorunun diğer yanıtlarına da bakın.


Orijinal Cevap

Bu özetin bazı örnekleri var, aşağıdaki örneklerden birini kopyaladım:

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

43

Bunun oldukça eski bir konu olduğunu biliyorum, ancak gelecekteki okuyucular için burada oldukça sezgisel bulduğum başka bir çözüm var:

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]*");
    }
}

Düzenleme: Önerilen iyileştirmeleriniz için none_ ve SCBoy'a teşekkürler .


1
Ondalık sayılar için hangi normal ifadenin kullanılacağını bilen var mı (ör. 123.456)? Validate (metin) işlevi parametresi "metin", metin alanındaki dizenin tamamı değil, kullanıcı tarafından düzenlenen son karakterdir, bu nedenle normal ifade doğru şekilde eşleşmeyebilir. Örneğin bu komutu şu şekilde kullanıyorum: text.matches("\\d+"); ve metin alanındaki herhangi bir karakteri silemiyorum
mils


1
Bunun iyi bir çözüm olduğunu düşünüyorum, ancak bir şeyi değiştirirdim. Text.matches ("[0-9] *") yazmak yerine, pattern için değişken oluşturup onu derlerdim. Kod kalıbınızda, birisi bir alana her karakter yazdığında derlenir ve bu, CPU ve bellek için maliyetlidir. Bu yüzden değişken ekleyeceğim: private static Pattern integerPattern = Pattern.compile ("[0-9] *"); Ve validate gövdesini şu şekilde değiştirin: integerPattern.matcher (metin) .matches ();
P. Jowko

38

JavaFX 8u40'tan başlayarak, bir metin alanına bir TextFormatter nesnesi ayarlayabilirsiniz:

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

Bu, text özelliğine bir değişiklik dinleyicisi eklediğinizde ve bu dinleyicideki metni değiştirdiğinizde alacağınız hem alt sınıflandırma hem de yinelenen değişiklik olaylarını önler.


30

TextInputBir sahip TextFormatterbiçimi, dönüştürmek için kullanılır ve giriş olabilir metin türlerinin sınırlamak edilebilir.

TextFormatterGiriş reddetmek için kullanılabilecek bir filtre vardır. Bunu, geçerli bir tam sayı olmayan herhangi bir şeyi reddedecek şekilde ayarlamalıyız. Ayrıca, dize değerini daha sonra bağlayabileceğimiz bir tamsayı değerine dönüştürmek için ayarlamamız gereken bir dönüştürücüye de sahiptir.

Yeniden kullanılabilir bir filtre oluşturalım:

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

Filtre üç şeyden birini yapabilir, değişikliği olduğu gibi kabul etmek için değiştirmeden iade edebilir, değişikliği uygun gördüğü bir şekilde değiştirebilir veya nulldeğişikliği hep birlikte reddetmek için geri dönebilir .

Standardı IntegerStringConverterdönüştürücü olarak kullanacağız .

Hepsini bir araya getirirsek:

TextField textField = ...;

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

textField.setTextFormatter(formatter);

Yeniden kullanılabilir bir filtreye ihtiyacınız yoksa, bunun yerine bu şık tek astarı yapabilirsiniz:

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

21

İstisnaları sevmiyorum, bu yüzden matchesString-Class işlevini kullandım

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
bazen bir istisnanız olur çünkü yumru çok büyük olabilir.
schlagi123

1
İpucu: "\\ d +" normal ifadesini "\\ d *" olarak değiştirin. Bu, metin giriş alanından tüm karakterleri kaldırmanıza izin verecektir (alanı temizlemek için geri al / sil kullanın).
Guus

1
Eski değere ayarladıktan sonra imleç konumunu ayarlamayı unutmayın:textField.positionCaret(textField.getLength());
hsson

İlk if koşulunu şu şekilde değiştirin: if (newValue.matches("\\d*") && newValue.getText().length < 5) bu durumda girişi 4 basamakla sınırlamak istiyorsanız.
Cappuccino 90

@ Cappuccino90 İfadeleri değiştirmelisiniz çünkü uzunluk kontrolü her vuruşta normal
ifadeyi

9

Java SE 8u40'tan başlayarak, böyle bir ihtiyaç için , klavyenin yukarı ok / aşağı ok tuşlarını veya yukarı ok / aşağı ok sağlanan düğmelerini kullanarak güvenli bir şekilde geçerli bir tamsayı seçmenize izin veren bir " tam sayı " kullanabilirsiniz Spinner.

Ayrıca , izin verilen değerleri sınırlamak için bir minimum , maksimum ve başlangıç değeri ve adım başına artırılacak veya azaltılacak bir miktar tanımlayabilirsiniz .

Örneğin

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

" Tam sayı " döndürücü ve " çift " döndürücü içeren sonuç örneği

görüntü açıklamasını buraya girin

Bir değer değişimi kullanıcının, sıralı bir değer dizisinden bir numara ya da bir nesne değer seçmesine olanak tanır tek satır metin alanı kontrolüdür. Döndürücüler tipik olarak dizinin öğeleri arasında gezinmek için bir çift küçük ok düğmesi sağlar. Klavyenin yukarı ok / aşağı ok tuşları da öğeler arasında geçiş yapar. Kullanıcının doğrudan iplik üreticisine bir (yasal) değer yazmasına da izin verilebilir. Birleşik giriş kutuları benzer işlevsellik sağlasa da, döndürücüler bazen önemli verileri gizleyebilecek bir açılır listeye ihtiyaç duymadıklarından ve ayrıca maksimum değerden minimum değere geri sarma gibi özelliklere izin verdikleri için tercih edilirler (örn. en büyük pozitif tam sayıdan 0'a).

Spinner kontrolü hakkında daha fazla ayrıntı


Kişiler, metin girişini onaylamamalı veya odak kaybolmamalıdır
geometrikal

7

Java 1.8 Lambdas kullanırsanız, tercih edilen cevap daha da küçük olabilir

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

Yan iftümce, 0.5d veya 0.7f gibi, Int.parseInt () tarafından doğru bir şekilde ayrıştırılan, ancak metin alanında görünmemesi gereken girdileri işlemek için önemlidir.


9
Woot? 0.5d ne zamandan beri Integer.parseInt () tarafından doğru bir şekilde ayrıştırılıyor ?! Bir java.lang.NumberFormatException atar: Girdi dizesi için: "0.5d" (beklendiği gibi, tamsayı olmadığından)
Burkhard

4

Bu basit kodu deneyin, işi yapacak.

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

Aynı dinleyiciyi birden fazla TextField'a uygulamak istiyorsanız, en basit çözüm şudur:

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

Bu benim için çalıştı.

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 cevabını TextFormatterJavaFX 8 ile birleştirme fikrime yardımcı olmak istiyorum.

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

çok iyi şanslar;) sakin ol ve java kodu


2

İşte bazı temel doğrulamaları TextFieldkullanan basit bir sınıf.TextFormatter JavaFX 8u40 tanıtıldı

DÜZENLE:

(Floern'in yorumuyla ilgili kod eklendi)

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

}

Bunu şu şekilde kullanabilirsiniz:

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

veya bunu bir fxml dosyasında başlatabilir ve uygun özelliklere sahip bir customTextField'a uygulayabilirsiniz.

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'daki kod


2

Kullandığım şey bu:

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

    }
});

Lambda gösteriminde aynı şey şöyle olacaktır:

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

2

Bu yöntem, TextField'ın tüm işlemleri bitirmesini sağlar (güvenli kopyalama / yapıştırma / geri alma). Sınıfları genişletmeyi gerektirmez ve her değişiklikten sonra yeni metinle ne yapacağınıza karar vermenize olanak tanır (onu mantığa itmek, önceki değere geri döndürmek, hatta değiştirmek için).

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

Durumunuz için sadece bu mantığı içine ekleyin. Mükemmel çalışıyor.

   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

Mmmm. Bu problemle haftalar önce karşılaştım. API bunu başarmak için bir kontrol sağlamadığından, kendi kontrolünüzü
kullanmak isteyebilirsiniz.
Şöyle bir şey kullandım:

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

Normal bir şekilde kullanılır TextBox,
ancak aynı zamanda valuegirilen tamsayıyı saklayan bir özelliğe de sahiptir .
Kontrol odağı kaybettiğinde, değeri doğrular ve geri döndürür (geçerli değilse).


2
Bu hangi dil?
Stealth Rabbi

It adlı JavaFX Script Haham, bu kadar eskimiş .
jewelsea

0

Bu Kod Metninizi Oluşturun Sadece Numara Kabul Edin

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

Kopyalamaya / yapıştırmaya çalışsanız bile bu kod benim için iyi çalışıyor.

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

    }
});

-1

JavaFX'in son güncellemelerinde, Platform.runLater yönteminde aşağıdaki gibi yeni metin ayarlamanız gerekir:

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

Düzeltme konumunu ayarlamak da iyi bir fikirdir.


1
Cevabınız için teşekkür ederim! Neden Platform.runLatergerekli olduğunu biraz açıklayabilir misiniz ?
TuringTux

@TuringTux, JavaFX'in son sürümünde, Platform.runLater'ı kullanmazsanız istisna atacak
bdshahab

-1

Evan Knowles cevabını iyileştirmek istiyorum: https://stackoverflow.com/a/30796829/2628125

Benim durumumda UI Bileşen kısmı için işleyicilerle sınıfım vardı. Başlatma:

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

Ve numbericSanitization yöntemi:

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

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

Anahtar kelime senkronize edildiEğer setText, eskisinin yürütülmesi tamamlanmadan çağrılacaksa, javafx'te olası oluşturma kilidi sorununu önlemek için sözcük eklenir. Yanlış karakterleri gerçekten hızlı yazmaya başlarsanız, yeniden oluşturmak kolaydır.

Diğer bir avantaj, eşleşecek tek bir model tutmanız ve sadece geri alma yapmanızdır. Bu daha iyidir çünkü farklı sterilizasyon modelleri için çözümü kolayca soyutlayabilirsiniz.


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

Bu, yalnızca tamsayı değeri ve ondalık değer (ASCII kodu 46 olan) girmenize izin verdiği için iyi çalışır.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.