1. /*
* This program is a loan payment calculator. It accepts a loan amount and
* number of years in text boxes from the user, then displays a table showing
* monthly payments and total payments for various interest rates, from 5% to 8%
* in increments of 0.125%, when a button is clicked. This allows the user to
* compare the effects of the various interest rates on the loan amount and
* period.
*
* Author: Bill Rutherford
*
*/
import javafx.application.Application;
import javafx.geometry.*;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.layout.*;
import javafx.scene.text.Font;
public class CalculateLoanPayments extends Application {
private TextField tfLoanAmount = new TextField();
private TextField tfNumberOfYears = new TextField();
private TextArea taPaymentTable = new TextArea();
private Tooltip ttLoanAmount = new Tooltip(
"Loan amount must be a nonnegative money amount");
private Tooltip ttNumberOfYears = new Tooltip(
"Number of years must be a nonnegative integer");
@Override
public void start(Stage primaryStage) {
final int SCENE_WIDTH = 555;
final int SCENE_HEIGHT = 250;
Button btShowTable = new Button("Show Table");
// Set text field properties
tfLoanAmount.setPrefColumnCount(10);
tfNumberOfYears.setPrefColumnCount(3);
// Create a pane for text fields and button
HBox inputPane = new HBox(10);
inputPane.setPadding(new Insets(10, 10, 10, 10));
inputPane.setAlignment(Pos.CENTER_LEFT);
inputPane.getChildren().addAll(new Label("Loan Amount "), tfLoanAmount,
new Label("tNumber of Years "), tfNumberOfYears, btShowTable);
// Set the button off to the right
HBox.setMargin(btShowTable, new Insets(0, 0, 0, SCENE_WIDTH - 505));
// Set text area properties
// Switch to a monospaced font; it's easier to get the columns to
// line up with it
taPaymentTable.setFont(Font.font("Lucida Console", 14));
taPaymentTable.setPrefRowCount(27);
taPaymentTable.setPrefColumnCount(60);
taPaymentTable.setEditable(false);
// Create a pane to hold the controls and text area
BorderPane mainPane = new BorderPane();
mainPane.setTop(inputPane);
mainPane.setCenter(new ScrollPane(taPaymentTable));
// Set event handlers
btShowTable.setOnAction(e -> showTable());
tfLoanAmount.setOnKeyTyped(e -> {
// Restore normal text color
tfLoanAmount.setStyle("-fx-text-fill: black");
2. // Turn off tooltip display
Tooltip.uninstall(tfLoanAmount, ttLoanAmount);
});
tfNumberOfYears.setOnKeyTyped(e -> {
tfNumberOfYears.setStyle("-fx-text-fill: black");
Tooltip.uninstall(tfNumberOfYears, ttNumberOfYears);
});
// Create a scene and place it in the stage
Scene scene = new Scene(mainPane, SCENE_WIDTH, SCENE_HEIGHT);
primaryStage.setTitle("Exercise 16_13");
primaryStage.setScene(scene);
primaryStage.show();
}
/** Create and display payment table */
public void showTable() {
int numberOfYears = getNumberOfYearsFromText();
double loanAmount = getLoanAmountFromText();
if (loanAmount >= 0.0 && numberOfYears >= 0) { // input is valid
// Declare table and create table header
StringBuilder table = new StringBuilder(
"Interest Ratet Monthly PaymenttTotal Payment");
// Create table body
for (Double interestRate = 5.0; interestRate <= 8.0;
interestRate += 0.125) {
String line = String.format("n%-5stt %-21.2f%-20.2f",
interestRate.toString(),
round(calculateMonthlyPayment(interestRate, loanAmount,
numberOfYears)),
round(calculateTotalPayment(interestRate, loanAmount,
numberOfYears)));
table.append(line);
}
// Display table
taPaymentTable.setText(table.toString());
}
// else do nothing; wait for the user to correct the errors
}
/** Get and validate the loan amount from the text field */
public double getLoanAmountFromText() {
double amount = 0.0;
boolean amountValid;
try {
amount = Double.parseDouble(tfLoanAmount.getText());
amountValid = (amount >= 0.0);
}
catch (NumberFormatException ex) {
amountValid = false;
}
if (amountValid)
return amount;
else { // set error indicators
tfLoanAmount.setStyle("-fx-text-fill: red");
// Set tooltip to display when the mouse is hovered over the
// text box
Tooltip.install(tfLoanAmount, ttLoanAmount);
// At least display a red cursor when the field is blank
// Display red text without the blue highlighting when it isn't
if (tfLoanAmount.getText().equals(""))
tfLoanAmount.requestFocus();
3. return -1.0; // return an error code
}
}
/** Get and validate the number of years from the text field */
public int getNumberOfYearsFromText() {
int years = 0;
boolean yearsValid;
try {
years = Integer.parseInt(tfNumberOfYears.getText());
yearsValid = (years >= 0);
}
catch (NumberFormatException ex) {
yearsValid = false;
}
if (yearsValid)
return years;
else { // set error indicators
tfNumberOfYears.setStyle("-fx-text-fill: red");
// Set tooltip to display when the mouse is hovered over the
// text box
Tooltip.install(tfNumberOfYears, ttNumberOfYears);
// At least display a red cursor when the field is blank
// Display red text without the blue highlighting when it isn't
if (tfNumberOfYears.getText().equals(""))
tfNumberOfYears.requestFocus();
return -1; // return an error code
}
}
/** Return monthly payment */
public double calculateMonthlyPayment(double interestRate,
double loanAmount, int numberOfYears) {
double monthlyInterestRate = interestRate / 1200;
return loanAmount * monthlyInterestRate / (1 - 1 /
Math.pow(1 + monthlyInterestRate, numberOfYears * 12));
}
/** Return total payment */
public double calculateTotalPayment(double interestRate,
double loanAmount, int numberOfYears) {
return calculateMonthlyPayment(interestRate, loanAmount, numberOfYears) *
numberOfYears * 12;
}
/** Round a money amount to the nearest cent */
// By creating this method and using it the way I did, I got the numbers
// to match the example in the book
public double round(double amount) {
return (int)(amount * 100) / 100.0;
}
public static void main(String[] args) {
launch(args);
}
}