3

Hi I am trying to read a the numbers from a text field that shows a price e.g. £3.00, and convert the value of the price to a double. Is there a way to do

Double value;
value = Double.parseDouble(textField.getText()); 

But it won't let me do that because of the £ sign. Is there a way to strip the pound sign then read the digits.

Thanks

S.Rose
  • 31
  • 1
  • 2
  • Taking into account that you will always have £, you can use `textField.getText().substring(1)` – ItachiUchiha Jan 29 '16 at 20:12
  • Perhaps `textField.getText().replaceAll("£","")` would be safer though... what if the user doesn't type "£", or if they put a space at the beginning, or... – James_D Jan 29 '16 at 20:16
  • Possible duplicate of [Java: remove all occurrences of char from string](http://stackoverflow.com/questions/4576352/java-remove-all-occurrences-of-char-from-string) or http://stackoverflow.com/questions/13386107/java-how-to-remove-single-character-from-a-string – fabian Jan 30 '16 at 00:03

1 Answers1

7

There is some TextFormatter and change filter handling logic built into the JavaFX TextField API, you could make use of that.

currency format

import javafx.application.Application;
import javafx.beans.binding.Bindings;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import javafx.util.StringConverter;

import java.text.DecimalFormat;
import java.text.ParseException;

class CurrencyFormatter extends TextFormatter<Double> {
    private static final double DEFAULT_VALUE = 5.00d;
    private static final String CURRENCY_SYMBOL = "\u00A3"; // british pound

    private static final DecimalFormat strictZeroDecimalFormat  
        = new DecimalFormat(CURRENCY_SYMBOL + "###,##0.00");

    CurrencyFormatter() {
        super(
                // string converter converts between a string and a value property.
                new StringConverter<Double>() {
                    @Override
                    public String toString(Double value) {
                        return strictZeroDecimalFormat.format(value);
                    }

                    @Override
                    public Double fromString(String string) {
                        try {
                            return strictZeroDecimalFormat.parse(string).doubleValue();
                        } catch (ParseException e) {
                            return Double.NaN;
                        }
                    }
                },
                DEFAULT_VALUE,
                // change filter rejects text input if it cannot be parsed.
                change -> {
                    try {
                        strictZeroDecimalFormat.parse(change.getControlNewText());
                        return change;
                    } catch (ParseException e) {
                        return null;
                    }
                }
        );
    }
}

public class FormattedTextField extends Application {

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

    @Override
    public void start(final Stage stage) {
        TextField textField = new TextField();
        textField.setTextFormatter(new CurrencyFormatter());

        Label text = new Label();
        text.textProperty().bind(
                Bindings.concat(
                        "Text: ",
                        textField.textProperty()
                )
        );

        Label value = new Label();
        value.textProperty().bind(
                Bindings.concat(
                        "Value: ",
                        textField.getTextFormatter().valueProperty().asString()
                )
        );

        VBox layout = new VBox(
                10,
                textField,
                text,
                value,
                new Button("Apply")
        );
        layout.setPadding(new Insets(10));

        stage.setScene(new Scene(layout));
        stage.show();
    }

}

The exact rules for DecimalFormat and the filter could get a little tricky if you are very particular about user experience (e.g. can the user enter the currency symbol? what happens if the user does not enter a currency symbol? are empty values permitted? etc.) The above example offers a compromise between a reasonable user experience and a (relatively) easy to program solution. For an actual production level application, you might wish to tweak the logic and behavior a bit more to fit your particular application.

Note, the apply button doesn't actually need to do anything to apply the change. Changes are applied when the user changes focus away from the text field (as long as they pass the change filter). So if the user clicks on the apply button, it gains, focus, the text field loses focus and the change is applied if applicable.

The above example treats the currency values as doubles (to match with the question), but those serious about currency may wish to look to BigDecimal.

For a simpler solution using similar concepts, see also:

Community
  • 1
  • 1
jewelsea
  • 150,031
  • 14
  • 366
  • 406