簡體   English   中英

如何在 JavaFX 的 TextField 中強制雙重輸入?

[英]How to force a double input in a TextField in JavaFX?

如何確保用戶在給定的 TextField 中只輸入雙倍值

我找到了整數解決方案,但我無法將其用於雙打。 我應該寫什么而不是"\\\\d*""[^\\\\d]"來使其適用於雙打?

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

如果用戶輸入無效值,則使用偵聽器並恢復為有效值的方法將起作用,但如果文本字段的textProperty上有其他偵聽器,則可能會產生問題。 這些偵聽器將觀察無效值以及有效值,因此他們必須知道過濾掉任何無效值。

更好的方法是使用TextFormatter TextFormatter可以做兩件事:

  1. 定義一個“過濾器”,它可以否決或修改對TextField文本所做的任何更改
  2. 定義一個“轉換器”,它定義了在您的情況下如何將文本與任何特定類型(例如Double )的值相互轉換。

定義適當的過濾器可能很棘手:您希望允許用戶進行任何合理的編輯。 這意味着用戶正在編輯時文本可能處於無效狀態; 例如,您可能希望允許文本字段完全為空,即使這並不代表有效值。 (否則,例如,如果他們想將“1”更改為“2”,就會讓用戶感到厭煩。)同樣,您可能希望允許諸如“-”和“.”之類的東西。

這是一個例子。 如果需要,過濾器應該修改傳遞給它的更改,並且可以返回null以完全否決更改。 此示例僅檢查文本是否表示有效的編輯狀態,如果是,則返回未修改的更改,否則否決它。 格式化程序需要處理過濾器允許的任何文本並將其轉換為雙精度。 這里任何不完整的東西都被表示為零。

Pattern validEditingState = Pattern.compile("-?(([1-9][0-9]*)|0)?(\\.[0-9]*)?");

UnaryOperator<TextFormatter.Change> filter = c -> {
    String text = c.getControlNewText();
    if (validEditingState.matcher(text).matches()) {
        return c ;
    } else {
        return null ;
    }
};

StringConverter<Double> converter = new StringConverter<Double>() {

    @Override
    public Double fromString(String s) {
        if (s.isEmpty() || "-".equals(s) || ".".equals(s) || "-.".equals(s)) {
            return 0.0 ;
        } else {
            return Double.valueOf(s);
        }
    }


    @Override
    public String toString(Double d) {
        return d.toString();
    }
};

TextFormatter<Double> textFormatter = new TextFormatter<>(converter, 0.0, filter);
TextField textField = new TextField();
textField.setTextFormatter(textFormatter);

如果需要,您可以使正則表達式更復雜,例如支持分組字符( "1,000.0" )、本地化( "1.003,14159"如果這適用於語言環境)或科學記數法表示( "6.022E23"等),並強制執行最小值或最大值等。您甚至可以執行諸如修改更改之類的操作,以便如果用戶在文本中的任何位置鍵入 a - ,它只會翻轉數字的符號。 (有關此類功能,請參閱TextFormatter.Change文檔。)

請注意,您可以直接從具有ObjectProperty<Double> valueProperty()的格式化程序獲取和設置雙ObjectProperty<Double> valueProperty()值(由轉換器提供ObjectProperty<Double> valueProperty() 所以你可以做這樣的事情

// update text field:
double value = ... ;
textFormatter.setValue(value);

// listen for changes in double value represented in text field
// Listener will be invoked when the user commits an edit:

textFormatter.valueProperty().addListener((ObservableValue<? extends Double> obs, Double oldValue, Double newValue) -> {
    System.out.println("User entered value: "+newValue.doubleValue());
});

這是一個 SSCCE。 第二個文本字段就在那里,以便您可以看到將焦點移動到不同控件的效果(如果值已更改,它會“提交”該值並調用文本格式化程序上的偵聽器;如果用戶按回車)。

import java.util.function.UnaryOperator;
import java.util.regex.Pattern;

import javafx.application.Application;
import javafx.beans.value.ObservableValue;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.TextField;
import javafx.scene.control.TextFormatter;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import javafx.util.StringConverter;

public class NumericTextField extends Application {

    @Override
    public void start(Stage primaryStage) throws Exception {
        Pattern validEditingState = Pattern.compile("-?(([1-9][0-9]*)|0)?(\\.[0-9]*)?");

        UnaryOperator<TextFormatter.Change> filter = c -> {
            String text = c.getControlNewText();
            if (validEditingState.matcher(text).matches()) {
                return c ;
            } else {
                return null ;
            }
        };

        StringConverter<Double> converter = new StringConverter<Double>() {

            @Override
            public Double fromString(String s) {
                if (s.isEmpty() || "-".equals(s) || ".".equals(s) || "-.".equals(s)) {
                    return 0.0 ;
                } else {
                    return Double.valueOf(s);
                }
            }


            @Override
            public String toString(Double d) {
                return d.toString();
            }
        };

        TextFormatter<Double> textFormatter = new TextFormatter<>(converter, 0.0, filter);
        TextField textField = new TextField();
        textField.setTextFormatter(textFormatter);

        textFormatter.valueProperty().addListener((ObservableValue<? extends Double> obs, Double oldValue, Double newValue) -> {
            System.out.println("User entered value: "+newValue.doubleValue());
        });

        VBox root = new VBox(5, textField, new TextField());
        root.setAlignment(Pos.CENTER);
        primaryStage.setScene(new Scene(root, 250, 250));
        primaryStage.show();
    }

    public static void main(String[] args) {
        launch(args);
    }

}

您可以在雙打上使用 java 正則表達式並用數字替換非數字字符。 您必須指定整數部分中允許的位數,例如 1,10。

textField.textProperty().addListener(new ChangeListener<String>() {
    @Override
    public void changed(ObservableValue<? extends String> observable, String oldValue, String newValue) {
        if (!newValue.matches("[0-9]{<range>}(\\.[0-9]*)?")) {
            textField.setText(newValue.replaceAll("[^\\d.]", ""));
            StringBuilder aus = new StringBuilder(newValue);
            boolean firstPointFound = false;
            for (int i = 0; i < aus.length(); i++){
                if(aus.charAt(i) == '.') {
                    if(!firstPointFound)
                        firstPointFound = true;
                    else
                        aus.deleteCharAt(i);
                }
            }
            newValue = aus.toString();
        }
    }
});

您可以使用 Double.parseDoubleDouble Javadoc 這將為您進行解析,而不是編寫您自己的雙重驗證。 然后,您可以檢查數字格式異常或空指針異常。

    try
    {
        Double.parseDouble(newValue);
        // Valid double
    }
    catch (NullPointerException | NumberFormatException ex)
    {
        // Not valid double
    }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM