Pergunta

I am trying to create a JavaFX calculator, a very basic one but I am unsure of how to implement the backspace.

private void makeBackspaceButton(Button button) {
    button.setStyle("-fx-base: ivory;");
    button.setOnAction(new EventHandler<ActionEvent>() {
        @Override
        public void handle(ActionEvent actionEvent) {
            value.set(value.get());
        }
    });

}

I cannot for the life of me think of a way to remove the last value that was entered. So that if the value 89 is entered only the last digit (9) will be removed. Is there a way to use it in this format or do I need to change my format. My full code is below, it is not finished yet.

import javafx.application.Application;
import javafx.beans.binding.Bindings;
import javafx.beans.property.*;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.input.KeyEvent;
import javafx.scene.layout.*;
import javafx.stage.Stage;
import javafx.stage.StageStyle;

import java.util.HashMap;
import java.util.Map;

// a simple JavaFX calculator.
public class Calcy extends Application {

//implementing the template if how i would like the buttons to look like
private static final String[][] template = {
    {"c", "%", "√", "←"},
    {"7", "8", "9", "/"},
    {"4", "5", "6", "*"},
    {"1", "2", "3", "-"},
    {"0", ".", "=", "+"}
};

private final Map<String, Button> accelerators = new HashMap<>();


private DoubleProperty stackValue = new SimpleDoubleProperty();
private DoubleProperty value = new SimpleDoubleProperty();

private enum Op {

    NOOP, ADD, SUBTRACT, MULTIPLY, DIVIDE
}

private Op curOp = Op.NOOP;
private Op stackOp = Op.NOOP;

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

@Override
public void start(Stage stage) {
    final TextField screen = createScreen();
    final TilePane buttons = createButtons();

    stage.setTitle("Thank goodness for a calculator!");
    stage.initStyle(StageStyle.UTILITY);
    stage.setResizable(false);
    stage.setScene(new Scene(createLayout(screen, buttons)));
    stage.show();
}

private VBox createLayout(TextField screen, TilePane buttons) {
    final VBox layout = new VBox(20);
    layout.setAlignment(Pos.CENTER);
    layout.setStyle("-fx-background-color: floralwhite; -fx-padding: 20; -fx-font-size: 20;");
    layout.getChildren().setAll(screen, buttons);
    handleAccelerators(layout);
    screen.prefWidthProperty().bind(buttons.widthProperty());
    return layout;
}

private void handleAccelerators(VBox layout) {
    layout.addEventFilter(KeyEvent.KEY_PRESSED, new EventHandler<KeyEvent>() {
        @Override
        public void handle(KeyEvent keyEvent) {
            Button activated = accelerators.get(keyEvent.getText());
            if (activated != null) {
                activated.fire();
            }
        }
    });
}

private TextField createScreen() {
    final TextField screen = new TextField();
    screen.setStyle("-fx-background-color: lightgrey;");
    screen.setAlignment(Pos.CENTER_RIGHT);
    screen.setEditable(false);
    screen.textProperty().bind(Bindings.format("%.2f", value));
    return screen;
}

private TilePane createButtons() {
    TilePane buttons = new TilePane();
    buttons.setVgap(7);
    buttons.setHgap(7);
    buttons.setPrefColumns(template[0].length);
    for (String[] r : template) {
        for (String s : r) {
            buttons.getChildren().add(createButton(s));
        }
    }
    return buttons;
}

private Button createButton(final String s) {
    Button button = makeStandardButton(s);

    if (s.matches("[0-9]")) {
        makeNumericButton(s, button);
    } else {
        final ObjectProperty<Op> triggerOp = determineOperand(s);
        if (triggerOp.get() != Op.NOOP) {
            makeOperandButton(button, triggerOp);
        } else if ("c".equals(s)) {
            makeClearButton(button);
        } else if ("=".equals(s)) {
            makeEqualsButton(button);
        } else if ("←".equals(s)) {
            makeBackspaceButton(button);
        } else if ("%".equals(s)) {
            makePercentageButton(button);
        } else if ("√".equals(s)) {
            makeSquarerootButton(button);
        } else if (".".equals(s)) {
            makePointButton(button);
        }
    }

    return button;
}

private ObjectProperty<Op> determineOperand(String s) {
    final ObjectProperty<Op> triggerOp = new SimpleObjectProperty<>(Op.NOOP);
    switch (s) {
        case "+":
            triggerOp.set(Op.ADD);
            break;
        case "-":
            triggerOp.set(Op.SUBTRACT);
            break;
        case "*":
            triggerOp.set(Op.MULTIPLY);
            break;
        case "/":
            triggerOp.set(Op.DIVIDE);
            break;
        case "%":

    }
    return triggerOp;
}

private void makeOperandButton(Button button, final ObjectProperty<Op> triggerOp) {
    button.setStyle("-fx-base: ivory;");
    button.setOnAction(new EventHandler<ActionEvent>() {
        @Override
        public void handle(ActionEvent actionEvent) {
            curOp = triggerOp.get();
        }
    });
}

private Button makeStandardButton(String s) {
    Button button = new Button(s);
    button.setStyle("-fx-base: ivory;");
    accelerators.put(s, button);
    button.setMaxSize(Double.MAX_VALUE, Double.MAX_VALUE);
    return button;
}

private void makeNumericButton(final String s, Button button) {
    button.setOnAction(new EventHandler<ActionEvent>() {
        @Override
        public void handle(ActionEvent actionEvent) {
            if (curOp == Op.NOOP) {
                value.set(value.get() * 10 + Integer.parseInt(s));
            } else {
                stackValue.set(value.get());
                value.set(Integer.parseInt(s));
                stackOp = curOp;
                curOp = Op.NOOP;
            }
        }
    });
}

private void makeClearButton(Button button) {
    button.setStyle("-fx-base: ivory;");
    button.setOnAction(new EventHandler<ActionEvent>() {
        @Override
        public void handle(ActionEvent actionEvent) {
            value.set(0);
        }
    });
}

private void makeBackspaceButton(Button button) {
    button.setStyle("-fx-base: ivory;");
    button.setOnAction(new EventHandler<ActionEvent>() {
        @Override
        public void handle(ActionEvent actionEvent) {
            value.set(value.get());
        }
    });

}

private void makeSquarerootButton(Button button) {
    button.setStyle("-fx-base: ivory;");
}

private void makePercentageButton(Button button) {
    button.setStyle("-fx-base: ivory;");
}

private void makePointButton(Button button) {
    button.setStyle("-fx-base: ivory;");
}

private void makeEqualsButton(Button button) {
    button.setStyle("-fx-base: ivory;");
    button.setOnAction(new EventHandler<ActionEvent>() {
        @Override
        public void handle(ActionEvent actionEvent) {
            switch (stackOp) {
                case ADD:
                    value.set(stackValue.get() + value.get());
                    break;
                case SUBTRACT:
                    value.set(stackValue.get() - value.get());
                    break;
                case MULTIPLY:
                    value.set(stackValue.get() * value.get());
                    break;
                case DIVIDE:
                    value.set(stackValue.get() / value.get());
                    break;
            }
        }
    });
}

}

Foi útil?

Solução

You can just add the following line inside the action method of the backspace button. This is just a normal operation which I did.

Getting the number, but the last one entered can be accessed by

(int)value.get()/10

Later, the decimal part can be accessed by

value.get() - (int)value.get())

So this is what goes

button.setOnAction(new EventHandler<ActionEvent>() {
    @Override
    public void handle(ActionEvent actionEvent) {
        value.set((int)value.get()/10 + 
        /**
        * To get the decimal part
        */
        value.get() - (int)value.get());
    }
});

The decimal part still doesn't work on your calculator, fix it as well. Once that is done, you will have to change the method to consider values before and after decimal !

Outras dicas

private void BackButtonActionPerformed(java.awt.event.ActionEvent evt) {

    if (OutputTextField.getText().length()>0){
        StringBuffer sb = new StringBuffer(OutputTextField.getText());
        sb = sb.deleteCharAt(OutputTextField.getText().length()-1);
        OutputTextField.setText(sb.toString());
    }
}     
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top