【问题标题】:Seprating the digits in the textfiled while entering the numbers (Javafx)输入数字时分隔文本字段中的数字(Javafx)
【发布时间】:2018-11-15 06:14:18
【问题描述】:

我创建了一个简单的 javafx 程序。当我在文本文件中输入数字时,我想将数字三三分开。我使用了stackoverflow链接中给出的两个解决方案(How to format text of TextField? JavaFXJava 8 U40 TextFormatter (JavaFX) to restrict user input only for decimal number

但他们都没有为我工作。第一个解决方案(设置 textformatter)对我来说没用(或者我可能无法以正确的方式使用它)但第二个解决方案正在工作但只接受 4 位数字,而我在文本字段中输入的其他数字是与我输入它们的样式相同,不带逗号。

我想像这样分隔每三个数字:12,564,546,554 如果有人知道解决方案,请帮助我克服这个问题。 谢谢。

 import javafx.application.Application;
 import javafx.scene.Scene;
 import javafx.scene.control.TextField;
 import javafx.scene.control.TextFormatter;
 import javafx.scene.layout.HBox;
 import javafx.stage.Stage;

 import java.text.DecimalFormat;
 import java.text.ParsePosition;


 public class DelimiterExample extends Application{


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


@Override
public void start(Stage primaryStage) throws Exception {

    TextField textField = new TextField();
    HBox hBox = new HBox();

    //solution one

    DecimalFormat format = new DecimalFormat( "#,###" );

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

    }));


    // solution two

    textField.textProperty().addListener((obs , oldVal , newVal)-> {

        if (newVal.matches("\\d*")) {
            DecimalFormat formatter = new DecimalFormat("#,###");
            String newvalstr = formatter.format(Float.parseFloat(newVal));
            //System.out.println(newvalstr);
            textField.setText(newvalstr);
        }


    });

    hBox.getChildren().add(textField);
    Scene scene = new Scene(hBox , 100 , 100);
    primaryStage.setScene(scene);
    primaryStage.show();
}
}

【问题讨论】:

  • 你想要逗号之间的数字,对吧?你试过String.split(String) 使用"," 作为参数吗?
  • 没有。我想在文本字段中输入数字时像这样格式化数字:145,636,826。我不想要逗号之间的数字,如你所说。我想在数字之间放置逗号以将它们格式化为货币。我第一次没有逗号。拆分功能不适合我的目标。
  • 啊,对不起,我误会了。
  • 没关系。谢谢您的回复。

标签: java javafx delimiter


【解决方案1】:

请大家不要重新发明轮子。 javafx.util.converter.NumberStringConverter 类为我们完成所有需要的工作:

TextField numberField = new TextField();
TextFormatter<Number> textFormatter = new TextFormatter<>(new NumberStringConverter());
numberField.setTextFormatter(textFormatter);

NumberStringConverter 是你的朋友;),如果你想在文本字段上监听正确的数字变化,只需使用下一个 textFormatter 属性(原谅对 textField 对象的直接方法调用):

textFormatter.valueProperty(); //Returns ObjectProperty<Number>

然后你可以检索任何类型的数字子类(number.intValue(), number.floatValue(), etc),只有当用户写入一个有效的数值时才会触发ChangeListener .

如果要手动为文本字段设置数字值:

float value = 1000f; //or any type of Number subclass
textFormatter.setValue(value);

P.D:NumberStringConverter 有一个 Locale 属性,可以更改该属性以应用所需国家/地区的适当格式。

【讨论】:

    【解决方案2】:

    再次感谢@fabian。我在这个问题上困扰了两天。我还发现我可以用这段代码拥有我想要的货币样式。现在我有两个完美的解决方案。

          textField.setOnKeyTyped(event -> {
            String typedCharacter = event.getCharacter();
            event.consume();
    
            if (typedCharacter.matches("\\d*")) {
                String currentText = 
                textField.getText().replaceAll("\\.","").replace(",", "");
                long longVal = Long.parseLong(currentText.concat(typedCharacter));
                textField.setText(new DecimalFormat("#,##0").format(longVal));
            }
        });
    

    【讨论】:

    • 我永远无法理解为什么开发人员经常不愿意使用可用的最高抽象......并创建脆弱的应用程序;)如果通过将文本粘贴或拖动文本输入到字段,所以它是不完整的。 Fabian 建议的 TextFormatter 是推荐的解决方案(自 fx8u40 起可用)
    【解决方案3】:

    任何不是选择更改的修改都可以通过修改范围之前的字符来修复:

    final char seperatorChar = ',';
    final Pattern p = Pattern.compile("[0-9" + seperatorChar + "]*");
    textField.setTextFormatter(new TextFormatter<>(c -> {
        if (!c.isContentChange()) {
            return c; // no need for modification, if only the selection changes
        }
        String newText = c.getControlNewText();
        if (newText.isEmpty()) {
            return c;
        }
        if (!p.matcher(newText).matches()) {
            return null; // invalid change
        }
    
        // invert everything before the range
        int suffixCount = c.getControlText().length() - c.getRangeEnd();
        int digits = suffixCount - suffixCount / 4;
        StringBuilder sb = new StringBuilder();
    
        // insert seperator just before caret, if necessary
        if (digits % 3 == 0 && digits > 0 && suffixCount % 4 != 0) {
            sb.append(seperatorChar);
        }
    
        // add the rest of the digits in reversed order
        for (int i = c.getRangeStart() + c.getText().length() - 1; i >= 0; i--) {
            char letter = newText.charAt(i);
            if (Character.isDigit(letter)) {
                sb.append(letter);
                digits++;
                if (digits % 3 == 0) {
                    sb.append(seperatorChar);
                }
            }
        }
    
        // remove seperator char, if added as last char
        if (digits % 3 == 0) {
            sb.deleteCharAt(sb.length() - 1);
        }
        sb.reverse();
        int length = sb.length();
    
        // replace with modified text
        c.setRange(0, c.getRangeEnd());
        c.setText(sb.toString());
        c.setCaretPosition(length);
        c.setAnchor(length);
    
        return c;
    }));
    

    【讨论】:

    • 完美。它就像一个魅力。这正是我想要的。非常感谢您的帮助。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-11
    • 2012-03-06
    相关资源
    最近更新 更多