【问题标题】:Editiing Currency with a TextField使用文本字段编辑货币
【发布时间】:2020-11-27 20:52:10
【问题描述】:

我如何获得一个 JavaFX 文本字段来编辑一种没有派系数字(例如长数字)存储的货币?使用 Databinding、TextFormatter 和其他 javaFX Stuff。

目标应该是:

  • 具有 LongProperty 的 Bo(货币价值以美分为单位)
  • 一个可编辑的文本字段,采用用户已知格式(可选的前导减号, 千位分隔符,小数分隔符,(货币符号),没有其他 字符可能)
  • Bo 和 TextField 之间的双向绑定。

【问题讨论】:

  • 请每个问题一个问题 - 首先解决纯文本字段,然后继续在单元格中使用它:)
  • 您希望将数据双向绑定到 textFormatter 的值(而不是字段的 textProperty)
  • 多谢指教,第一个拆分回答。
  • 你把你的问题弄得一团糟;)应该反过来:这是开始(基本问题绑定与属性和 textField 输入之间的转换),后续将应用细胞的基础溶液。请注意,其他问题无法回答 - 没有您在此处提供的详细信息!
  • 严格来说,这仍然无法回答(因为所有细节都在答案中) - 理想情况下,您可以将代码示例保留在这里(就像一开始一样)并将答案编辑为仅包含更改的接线(从 textField.textProperty 到 formatter.valueProperty)。请注意,SO 的目标是建立一个对未来读者有用的知识库 - 这将期望问题上下文中的 .. 问题 :) 但是,改进了很多 .. 谢谢 :)

标签: java javafx binding currency


【解决方案1】:

这是一个解决方案(可能不是最好的,如果我可以改进,请发表评论)

博:

import java.util.Random;

import javafx.beans.property.LongProperty;
import javafx.beans.property.SimpleLongProperty;

public class SimpleBo {
        //a simple LongProperty to store the currency without fractional digits (56,81 € would be 5681)
        private LongProperty currencyLong = new SimpleLongProperty();
        public SimpleBo() {
            setCurrencyLong(new Random().nextLong());
        }
        public final LongProperty currencyLongProperty() {
            return this.currencyLong;
        }
        public final long getCurrencyLong() {
            return this.currencyLongProperty().get();
        }
        public final void setCurrencyLong(final long currencyLong) {
            this.currencyLongProperty().set(currencyLong);
        }
}

数字到字符串转换器:

import java.text.NumberFormat;
import java.util.Locale;

import javafx.util.converter.NumberStringConverter;

public class MyNumberStringConverter extends NumberStringConverter {
    public MyNumberStringConverter() {
        super();
    }

    public MyNumberStringConverter(Locale locale, String pattern) {
        super(locale, pattern);
    }

    public MyNumberStringConverter(Locale locale) {
        super(locale);
    }

    public MyNumberStringConverter(NumberFormat numberFormat) {
        super(numberFormat);
    }

    public MyNumberStringConverter(String pattern) {
        super(pattern);
    }

    @Override
    public Number fromString(String value) {
        //to transform the double, given by the textfield, just multiply by 100 and round if any left
        Number rValue = Math.round(super.fromString(value).doubleValue() * 100);
        return rValue.longValue();
    }

    @Override
    public String toString(Number value) {
        if(value == null) {
            return "";
        }
        //Check for too big long value
        //If the long is too big, it could result in a strange double value.
        if(value.longValue() > 1000000000000l || value.longValue() < -1000000000000l ) {
            return "";
        }
        BigDecimal myBigDecimal = new BigDecimal(value.longValue());
        //to convert the long to a double (currency with fractional digits)
        myBigDecimal = myBigDecimal.movePointLeft(2);
        double asDouble = myBigDecimal.doubleValue();
        if(asDouble == Double.NEGATIVE_INFINITY || asDouble == Double.POSITIVE_INFINITY) {
            return "";
        }
        return super.toString(asDouble);
    }

实用类:

import java.util.function.UnaryOperator;
import javafx.scene.control.TextFormatter;

public class Util {

    // This will filter the changes
    public static UnaryOperator<TextFormatter.Change> createFilter() {
        //this is a simple Regex to define the acceptable Chars
        String validEditingStateRegex = "[0123456789,.-]*";
        return change -> {
            String text = change.getText();
            //Check if something changed and just return if not
            if (!change.isContentChange()) {
                return change;
            }
            //check if the changed text validates against the regex
            if (text.matches(validEditingStateRegex) || text.isEmpty()) {
                //if valid return the change
                return change;
            }
            //otherwise return null
            return null;
        };
    }
}

测试应用:

import java.text.NumberFormat;
import javafx.application.Application;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.control.TextFormatter;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

public class BindingExample extends Application {

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

    @Override
    public void start(Stage primaryStage) throws Exception {
        Scene scene = new Scene(createBindingExample());
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    //Creates just a sample gui with a Business Objekt 
    public static Parent createBindingExample() {
        VBox vbox = new VBox();
        SimpleBo myBo = new SimpleBo();
        TextField myTextField = new TextField();
        Label fooLabel = new Label();

        //Setting up the textField with a Formatter
        NumberFormat nFormat = NumberFormat.getInstance();
        //Define the integer and fractional digits
        nFormat.setMinimumIntegerDigits(1);
        nFormat.setMaximumFractionDigits(2);
        //setting up the TextFormatter with the NumberFormat and a Filter to limit the inputchars
        TextFormatter<Number> textFormatter = new TextFormatter<>(new MyNumberStringConverter(nFormat), 0l,
                Util.createFilter());
        //Bind (Bidirectional) the BO currency value to the textformatter value
        textFormatter.valueProperty().bindBidirectional(myBo.currencyLongProperty());
        myTextField.setTextFormatter(textFormatter);

        //just to show the currency value, bind it to the label
        fooLabel.textProperty().bind(myBo.currencyLongProperty().asString());

        vbox.getChildren().add(myTextField);
        //just for spacing
        vbox.getChildren().add(new Label(" "));
        vbox.getChildren().add(fooLabel);
        return vbox;
    }
}

您可以继续将 TextField 放入 HBox 和货币符号的标签中。或者使用货币符号的保管箱或其他任何东西。可以将 NumberFormat 与 Currency 一起使用,因此格式会添加符号。但这还有一些其他的缺点,所以我就这样走了。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-02
    • 2013-07-03
    相关资源
    最近更新 更多