13.6 (Tip Calculator Modification) The Tip Calculator app from Section 12.5 does
ID: 3710666 • Letter: 1
Question
13.6 (Tip Calculator Modification) The Tip Calculator app from Section 12.5 does not need a Button to perform its calculations. Reimplement this app to use property listeners to perform the calculations whenever the user modifies the bill amount or changes the custom tip percentage. Also use a property binding to update the Label that displays the tip percentage.
Please only respond with complete answer.
Starting code:
// Fig. 12.19: TipCalculator.java
// Main application class that loads and displays the Tip Calculator's GUI.
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
public class TipCalculator extends Application {
@Override
public void start(Stage stage) throws Exception {
Parent root =
FXMLLoader.load(getClass().getResource("TipCalculator.fxml"));
Scene scene = new Scene(root); // attach scene graph to scene
stage.setTitle("Tip Calculator"); // displayed in window's title bar
stage.setScene(scene); // attach scene to stage
stage.show(); // display the stage
}
public static void main(String[] args) {
// create a TipCalculator object and call its start method
launch(args);
}
}
/**************************************************************************
* (C) Copyright 1992-2018 by Deitel & Associates, Inc. and *
* Pearson Education, Inc. All Rights Reserved. *
* *
* DISCLAIMER: The authors and publisher of this book have used their *
* best efforts in preparing the book. These efforts include the *
* development, research, and testing of the theories and programs *
* to determine their effectiveness. The authors and publisher make *
* no warranty of any kind, expressed or implied, with regard to these *
* programs or to the documentation contained in these books. The authors *
* and publisher shall not be liable in any event for incidental or *
* consequential damages in connection with, or arising out of, the *
* furnishing, performance, or use of these programs. *
*************************************************************************/
////
// TipCalculatorController.java
// Controller that handles calculateButton and tipPercentageSlider events
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.NumberFormat;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.control.Label;
import javafx.scene.control.Slider;
import javafx.scene.control.TextField;
public class TipCalculatorController {
// formatters for currency and percentages
private static final NumberFormat currency =
NumberFormat.getCurrencyInstance();
private static final NumberFormat percent =
NumberFormat.getPercentInstance();
private BigDecimal tipPercentage = new BigDecimal(0.15); // 15% default
// GUI controls defined in FXML and used by the controller's code
@FXML
private TextField amountTextField;
@FXML
private Label tipPercentageLabel;
@FXML
private Slider tipPercentageSlider;
@FXML
private TextField tipTextField;
@FXML
private TextField totalTextField;
// calculates and displays the tip and total amounts
@FXML
private void calculateButtonPressed(ActionEvent event) {
try {
BigDecimal amount = new BigDecimal(amountTextField.getText());
BigDecimal tip = amount.multiply(tipPercentage);
BigDecimal total = amount.add(tip);
tipTextField.setText(currency.format(tip));
totalTextField.setText(currency.format(total));
}
catch (NumberFormatException ex) {
amountTextField.setText("Enter amount");
amountTextField.selectAll();
amountTextField.requestFocus();
}
}
// called by FXMLLoader to initialize the controller
public void initialize() {
// 0-4 rounds down, 5-9 rounds up
currency.setRoundingMode(RoundingMode.HALF_UP);
// listener for changes to tipPercentageSlider's value
tipPercentageSlider.valueProperty().addListener(
new ChangeListener<Number>() {
@Override
public void changed(ObservableValue<? extends Number> ov,
Number oldValue, Number newValue) {
tipPercentage =
BigDecimal.valueOf(newValue.intValue() / 100.0);
tipPercentageLabel.setText(percent.format(tipPercentage));
}
}
);
}
}
/**************************************************************************
* (C) Copyright 1992-2018 by Deitel & Associates, Inc. and *
* Pearson Education, Inc. All Rights Reserved. *
* *
* DISCLAIMER: The authors and publisher of this book have used their *
* best efforts in preparing the book. These efforts include the *
* development, research, and testing of the theories and programs *
* to determine their effectiveness. The authors and publisher make *
* no warranty of any kind, expressed or implied, with regard to these *
* programs or to the documentation contained in these books. The authors *
* and publisher shall not be liable in any event for incidental or *
* consequential damages in connection with, or arising out of, the *
* furnishing, performance, or use of these programs. *
*************************************************************************/
////
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.Slider?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.ColumnConstraints?>
<?import javafx.scene.layout.GridPane?>
<?import javafx.scene.layout.RowConstraints?>
<GridPane hgap="8.0" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" xmlns="http://javafx.com/javafx/8.0.60" xmlns:fx="http://javafx.com/fxml/1" fx:controller="TipCalculatorController">
<columnConstraints>
<ColumnConstraints halignment="RIGHT" hgrow="SOMETIMES" minWidth="10.0" />
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" />
</columnConstraints>
<rowConstraints>
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
</rowConstraints>
<children>
<Label text="Amount" />
<Label fx:id="tipPercentageLabel" text="15%" GridPane.rowIndex="1" />
<Label text="Tip" GridPane.rowIndex="2" />
<Label text="Total" GridPane.rowIndex="3" />
<TextField fx:id="amountTextField" GridPane.columnIndex="1" />
<TextField fx:id="tipTextField" editable="false" focusTraversable="false" GridPane.columnIndex="1" GridPane.rowIndex="2" />
<TextField fx:id="totalTextField" editable="false" focusTraversable="false" GridPane.columnIndex="1" GridPane.rowIndex="3" />
<Slider fx:id="tipPercentageSlider" blockIncrement="5.0" max="30.0" value="15.0" GridPane.columnIndex="1" GridPane.rowIndex="1" />
<Button maxWidth="1.7976931348623157E308" mnemonicParsing="false" text="Calculate" GridPane.columnIndex="1" GridPane.rowIndex="4" />
</children>
<padding>
<Insets bottom="14.0" left="14.0" right="14.0" top="14.0" />
</padding>
</GridPane>
Explanation / Answer
package tipcalculator;
// Fig. 12.19: TipCalculator.java
// Main application class that loads and displays the Tip Calculator's GUI.
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
public class TipCalculator extends Application {
@Override
public void start(Stage stage) throws Exception {
Parent root =
FXMLLoader.load(getClass().getResource("TipCalculator.fxml"));
Scene scene = new Scene(root); // attach scene graph to scene
stage.setTitle("Tip Calculator"); // displayed in window's title bar
stage.setScene(scene); // attach scene to stage
stage.show(); // display the stage
}
public static void main(String[] args) {
// create a TipCalculator object and call its start method
launch(args);
}
}
package tipcalculator;
/**
* ************************************************************************
* (C) Copyright 1992-2018 by Deitel & Associates, Inc. and * Pearson Education,
* Inc. All Rights Reserved. * * DISCLAIMER: The authors and publisher of this
* book have used their * best efforts in preparing the book. These efforts
* include the * development, research, and testing of the theories and programs
* * to determine their effectiveness. The authors and publisher make * no
* warranty of any kind, expressed or implied, with regard to these * programs
* or to the documentation contained in these books. The authors * and publisher
* shall not be liable in any event for incidental or * consequential damages in
* connection with, or arising out of, the * furnishing, performance, or use of
* these programs. *
************************************************************************
*/
////
// TipCalculatorController.java
// Controller that handles calculateButton and tipPercentageSlider events
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.NumberFormat;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.control.Label;
import javafx.scene.control.Slider;
import javafx.scene.control.TextField;
public class TipCalculatorController {
// formatters for currency and percentages
private static final NumberFormat currency
= NumberFormat.getCurrencyInstance();
private static final NumberFormat percent
= NumberFormat.getPercentInstance();
private BigDecimal tipPercentage = new BigDecimal(0.15); // 15% default
// GUI controls defined in FXML and used by the controller's code
@FXML
private TextField amountTextField;
@FXML
private Label tipPercentageLabel;
@FXML
private Slider tipPercentageSlider;
@FXML
private TextField tipTextField;
@FXML
private TextField totalTextField;
// calculates and displays the tip and total amounts
@FXML
private void calculateButtonPressed(ActionEvent event) {
try {
BigDecimal amount = new BigDecimal(amountTextField.getText());
BigDecimal tip = amount.multiply(tipPercentage);
BigDecimal total = amount.add(tip);
tipTextField.setText(currency.format(tip));
totalTextField.setText(currency.format(total));
} catch (NumberFormatException ex) {
amountTextField.setText("Enter amount");
amountTextField.selectAll();
amountTextField.requestFocus();
}
}
// called by FXMLLoader to initialize the controller
public void initialize() {
// 0-4 rounds down, 5-9 rounds up
currency.setRoundingMode(RoundingMode.HALF_UP);
// listener for changes to tipPercentageSlider's value
tipPercentageSlider.valueProperty().addListener(
new ChangeListener<Number>() {
@Override
public void changed(ObservableValue<? extends Number> ov,
Number oldValue, Number newValue) {
//Commented because this code done using Property Binding in FXML file
/* tipPercentage
= BigDecimal.valueOf(newValue.intValue() / 100.0);
tipPercentageLabel.setText(percent.format(tipPercentage));
*/
try {
tipPercentage=BigDecimal.valueOf(Double.parseDouble(tipPercentageLabel.getText()));
BigDecimal amount = new BigDecimal(amountTextField.getText());
BigDecimal tip = amount.multiply(tipPercentage);
BigDecimal total = amount.add(tip);
tipTextField.setText(currency.format(tip));
totalTextField.setText(currency.format(total));
} catch (NumberFormatException ex) {
amountTextField.setText("Enter amount");
amountTextField.selectAll();
amountTextField.requestFocus();
}
}
}
);
//Listener to change the values based on the change in Text Field Values
amountTextField.textProperty().addListener((observable, oldValue, newValue) -> {
try {
//get new Value
BigDecimal amount = new BigDecimal(newValue);
BigDecimal tip = amount.multiply(tipPercentage);
BigDecimal total = amount.add(tip);
tipTextField.setText(currency.format(tip));
totalTextField.setText(currency.format(total));
} catch (NumberFormatException ex) {
amountTextField.setText("Enter amount");
amountTextField.selectAll();
amountTextField.requestFocus();
}
});
}
}
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.Slider?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.ColumnConstraints?>
<?import javafx.scene.layout.GridPane?>
<?import javafx.scene.layout.RowConstraints?>
<GridPane hgap="8.0" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" xmlns="http://javafx.com/javafx/8.0.102" xmlns:fx="http://javafx.com/fxml/1" fx:controller="tipcalculator.TipCalculatorController">
<columnConstraints>
<ColumnConstraints halignment="RIGHT" hgrow="SOMETIMES" minWidth="10.0" />
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" />
</columnConstraints>
<rowConstraints>
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
</rowConstraints>
<children>
<Label text="Amount" />
<Label fx:id="tipPercentageLabel" text="${tipPercentageSlider.value}" GridPane.rowIndex="1" />
<Label text="Tip" GridPane.rowIndex="2" />
<Label text="Total" GridPane.rowIndex="3" />
<TextField fx:id="amountTextField" GridPane.columnIndex="1" />
<TextField fx:id="tipTextField" editable="false" focusTraversable="false" GridPane.columnIndex="1" GridPane.rowIndex="2" />
<TextField fx:id="totalTextField" editable="false" focusTraversable="false" GridPane.columnIndex="1" GridPane.rowIndex="3" />
<Slider fx:id="tipPercentageSlider" blockIncrement="5.0" max="30.0" showTickLabels="true" showTickMarks="true" value="15.0" GridPane.columnIndex="1" GridPane.rowIndex="1" />
<Button maxWidth="1.7976931348623157E308" mnemonicParsing="false" text="Calculate" GridPane.columnIndex="1" GridPane.rowIndex="4" />
</children>
<padding>
<Insets bottom="14.0" left="14.0" right="14.0" top="14.0" />
</padding>
</GridPane>
Output:
Related Questions
Navigate
Integrity-first tutoring: explanations and feedback only — we do not complete graded work. Learn more.