I am creating a GUI calculator. When I enter amounts and press submit, negative infinity appears in the monthly payment area instead of the dollar amount. I'm not sure what is causing the problem. My code consist of three files: the GUI, calculation, and text file.
GUI
import java.awt.*;
import java.awt.event.*;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.text.NumberFormat;
import javax.swing.*;
/**
*
* @author Chantelle Dawson
*/
public class Week5_2 extends JFrame implements ActionListener {
private Container contentPane = null;
private JSplitPane split ;
private JPanel lfPanel ;
private JScrollPane rtPanel ;
private JLabel jl_principal ;
private JTextField tf_principal;
private JLabel jl_menu ;
private JComboBox jcb_menu ;
private JLabel jl_monthlyPayment ;
private JTextField tf_monthlyPayment ;
private JTextArea amortization;
private JButton submit;
private JButton reset;
private JButton exit;
private String[] comboMenu = {"7 years at 5.35%", "15 years at 5.5%", "30 years at 5.75%"};
private String[] interestRates;
private NumberFormat fmt = NumberFormat.getInstance();
public Week5_2(){
super();
initalize();
}
private void initalize(){
interestRates = loadInterestRates("loadtest.txt");
// set up the number formatter
fmt.setGroupingUsed(true);
fmt.setMaximumFractionDigits(2);
fmt.setMinimumFractionDigits(2);
contentPane = this.getContentPane();
setTitle(" Mortgage Calculator");
setSize(800, 600);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// set top pane with BoxLayout
contentPane.setLayout(new BoxLayout(contentPane, BoxLayout.X_AXIS));
// create a splitpane to layout out code
split = new JSplitPane();
// make the splitter up and down
split.setOrientation(JSplitPane.VERTICAL_SPLIT);
split.setDividerSize(2);
split.setDividerLocation(200); // set the divider a little off from the middle
//splitpane.setEnabled(false); // locks the divider bar
// Call the method to load the left side of the split pane
loadLeftSide();
// load the right side of the split pane
loadRightSide();
// add the split pane to the content pane
contentPane.add(split, null);
}
private String [] loadInterestRates(String filename)
{
// 3 entries in your file
String [] retval = new String [3];
int index = 0;
try
{
File fromFile = new File(filename);
BufferedReader reader = new BufferedReader(new FileReader(fromFile));
String line = reader.readLine();
while(line != null)
{
retval[index] = line;
line = reader.readLine();
index++;
}
return retval;
}
catch (IOException e)
{
System.err.println(e.getMessage());
return null;
}
}
private void loadRightSide()
{
// display amortization chart in Text Area
rtPanel = new JScrollPane();
// make the scroll bars always be there
rtPanel.setHorizontalScrollBarPolicy(javax.swing.JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
rtPanel.setVerticalScrollBarPolicy(javax.swing.JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
// create border
rtPanel.setViewportBorder(javax.swing.BorderFactory.createBevelBorder(javax.swing.border.BevelBorder.LOWERED));
amortization = new JTextArea();
Font displayFont = new Font("Serif", Font.BOLD, 14);
// makes text area uneditable
amortization.setEditable(false);
amortization.setFont(displayFont);
rtPanel.setViewportView(amortization);
split.setRightComponent(rtPanel);
}
private void loadLeftSide (){
lfPanel = new JPanel();
lfPanel.setComponentOrientation(java.awt.ComponentOrientation.LEFT_TO_RIGHT);
// add border to panel
lfPanel.setBorder(new javax.swing.border.SoftBevelBorder(javax.swing.border.SoftBevelBorder.LOWERED));
//set Grid layout of left panel
lfPanel.setLayout(new GridLayout(5,2));
//create labels and set text that appears on label
jl_principal = new JLabel ("Mortgage Amount");
jl_menu = new JLabel ("Term and Interest");
jl_monthlyPayment = new JLabel ("Monthly Payment");
//create combo box and text fields
jcb_menu = new JComboBox(comboMenu);
jcb_menu.setEditable(false);
tf_principal = new JTextField();
tf_monthlyPayment = new JTextField();
tf_monthlyPayment.setEditable(false);
//create buttons
submit = new JButton ("Submit");
//add action listener
submit.addActionListener(this);
exit = new JButton ("Exit");
//add action listener
exit.addActionListener(this);
reset = new JButton ("Reset");
//add action listener
reset.addActionListener(this);
//lay out components on pane
lfPanel.add(jl_principal);
lfPanel.add(tf_principal);
lfPanel.add(jl_menu);
lfPanel.add(jcb_menu);
lfPanel.add(jl_monthlyPayment);
lfPanel.add(tf_monthlyPayment);
lfPanel.add(submit);
lfPanel.add(exit);
lfPanel.add(new JLabel(""));//empty cell
lfPanel.add(reset);
split.setLeftComponent(lfPanel);
}
public void actionPerformed(ActionEvent e)
{
Object source = e.getSource();
if (source == exit)//enables exit button to operate
{
System.exit(0);
}
if (source == reset)//enables reset button to operate
{
tf_principal.setText("");
tf_monthlyPayment.setText("");
amortization.setText("");
}
if(source == jcb_menu)//enables combo box to set selection by user
{
double select = (double) jcb_menu.getSelectedIndex();
jcb_menu.setSelectedIndex((int) (double) select);
}
int years;
double annualInterest;
int indexOne = jcb_menu.getSelectedIndex();//gets selected term and interest from combo box
double monthlyInt;
if (source == submit)//calculates mortgage when submit button is pushed
{
try
{
double principle = Double.parseDouble(tf_principal.getText().trim());
if(indexOne == 0)
{
years = 7;
annualInterest = Double.parseDouble(interestRates[0]);
}
if (indexOne == 1)
{
years = 15;
annualInterest = Double.parseDouble(interestRates[1]);
}
if (indexOne == 2)
{
years = 30;
annualInterest = Double.parseDouble(interestRates[2]);
}//end index if
annualInterest = 0;
years = 0;
monthlyInt = (double) ((annualInterest / 100)/12);
Week5_2Cal calc = new Week5_2Cal (principle, years, (int) monthlyInt);
if(principle>0){//prevent negative numbers from being used
tf_monthlyPayment.setText("" + fmt.format(calc.getMonthlypayment()));//Gets mortgage payment from Calculation class and assigns to payment.
amortization.setText(calc.getAmortizationTableAsString());//Gets amortization schedule from Calculation class and assigns to JTextArea
} //if set payment
}//ends try
catch(NumberFormatException nfe)
{
JOptionPane.showMessageDialog(null, "Please make sure all your entries are numeric!", "USER INPUT ERROR", JOptionPane.ERROR_MESSAGE);
} //ends catch
}//ends submit if
}//ends action listener
public static void main(String[] args) {
Week5_2 w5 = new Week5_2();
w5.setVisible(true);
}//ends main
}//ends class
Calculation:
import java.text.NumberFormat;
public class Week5_2Cal
{
// member variables
private double principal = -1.0;
private double annualInterest = -1.0;
private int years = -1;
private double monthlyInt = -1.0;
private int numberofpayments = -1; // total number of payments for loan
private double monthlypayment = -1;
private double[] interest_paid = null;
private double[] principal_paid = null;
private double[] balance = null;
private double[] previous_balance = null;
private NumberFormat fmt = NumberFormat.getInstance();
/**
* @param principal
* @param annualInterest
* @param years
*/
Week5_2Cal(double principal, int years, double monthlyInt) {
this.principal = principal;
this.annualInterest = annualInterest;
this.years = years;
monthlyInt = annualInterest / 12;
numberofpayments = years * 12;
interest_paid = new double[numberofpayments];
principal_paid = new double[numberofpayments];
balance = new double[numberofpayments];
previous_balance = new double[numberofpayments];
// set up the number formatter... BTW there is also a currency formatter
fmt.setGroupingUsed(true);
fmt.setMaximumFractionDigits(2);
fmt.setMinimumFractionDigits(2);
calculatePayment();
buildAmortizationTable();
}
/**
* Caluclates the monthly payment.
*/
private void calculatePayment()
{
monthlypayment = (principal * monthlyInt) / (1 - Math.pow(1 / (1 + monthlyInt), years * 12));
}
public double getMonthlypayment()
{
return monthlypayment;
}
public void buildAmortizationTable()
{
int paymentnumber = 0;
double mnth_balance = principal;
double mnth_interest;
double princ;
// loop
while (paymentnumber < numberofpayments)
{
previous_balance[paymentnumber] = mnth_balance;
mnth_interest = mnth_balance * (annualInterest / 12);
interest_paid[paymentnumber] = mnth_interest;
princ = monthlypayment - mnth_interest;
principal_paid[paymentnumber] = princ;
mnth_balance = mnth_balance - princ;
balance[paymentnumber] = mnth_balance;
paymentnumber++;
}
}
/**
* Builds a displayable amortization table.
*
* @return
*/
public String getAmortizationTableAsString()
{
StringBuffer buffer = new StringBuffer();
int paymentnumber = 0;
buffer.append("Payment #\tBalance\t\t Principle Paid \t Interest Paid\t\t New Balance \n");
while (paymentnumber < numberofpayments)
{
// Show a full year of payments and then temporarily pause program
// execution
buffer.append((paymentnumber + 1) + "\t $" + fmt.format(previous_balance[paymentnumber]) + "\t\t $"
+ fmt.format(principal_paid[paymentnumber]) + "\t\t $" + fmt.format(interest_paid[paymentnumber])
+ "\t\t $" + fmt.format(balance[paymentnumber]) + "\n");
if ((paymentnumber + 1) % 12 == 0)
{
buffer.append("\n-------------------------------------------------------------------------\n");
}
paymentnumber++;
}
return buffer.toString();
}
// Adds getters and setters
/**
* @return Returns the annualInterest.
*/
public double getAnnualInterest()
{
return annualInterest;
}
/**
* @param annualInterest
* The annualInterest to set.
*/
public void setAnnualInterest(double annualInterest)
{
this.annualInterest = annualInterest;
monthlyInt = annualInterest / 12;
// calculate the new values
calculatePayment();
buildAmortizationTable();
}
/**
* @return Returns the principal.
*/
public double getPrincipal()
{
return principal;
}
/**
* @param principal
* The principal to set.
*/
public void setPrincipal(double principal)
{
this.principal = principal;
// calculate the new values
calculatePayment();
buildAmortizationTable();
}
/**
* @return Returns the years.
*/
public int getYears()
{
return years;
}
/**
* @param years
* The years to set.
*/
public void setYears(int years)
{
this.years = years;
numberofpayments = years * 12;
// need to re-allocate all the arrays
interest_paid = new double[numberofpayments];
principal_paid = new double[numberofpayments];
balance = new double[numberofpayments];
previous_balance = new double[numberofpayments];
// calculate the new values
calculatePayment();
buildAmortizationTable();
}
/**
* @return Returns the monthlyInt.
*/
public double getMonthlyInt()
{
return monthlyInt;
}
/**
* @return Returns the numberofpayments.
*/
public int getNumberofpayments()
{
return numberofpayments;
}
/**
* This is the entry point to the application. No calculation here, just
* creating the classes and calling a few methods.
*
* @param args
*/
public static void main(String args[])
{
// now the mortgage calculator can be used for any input
Week5_2Cal my_mort = new Week5_2Cal(355000, (int) 5.35, 15);
System.out.print(my_mort.getAmortizationTableAsString());
// now the class can be used manually too
my_mort.setAnnualInterest(5.5);
my_mort.setPrincipal(355000);
my_mort.setYears(15);
System.out.print(my_mort.getAmortizationTableAsString());
// or create another instance
Week5_2Cal my_mort2 = new Week5_2Cal(355000, (int) 5.75, 30);
System.out.print(my_mort2.getAmortizationTableAsString());
}
}
Text File:
5.35
5.5
5.75