I have spent over a WEEK trying to figure out why my code isn't working. It's a long code, I will post it all but I will break down the code as I explain.
First off, I have called double[] arrays and then initialized them later on in the program on certain steps. What problem is that even though they are initialized, later on in the code, it's telling me that the double[] I'm requesting is NULL, as if it didn't know that I have already done all that and added elements to it. Here's the program.....
package usefulapps;
/*
File: MortgageCalculator2.java
This file calculates the monthly payments of a user inputs for a mortgage.
*/
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.text.DecimalFormat;
/* import java package: classes to handle I/O methods,
including FileReader, InputStreamReader, and BufferedReader.
*/
@SuppressWarnings("serial")
public class MortgageCalculator3 extends JFrame implements ActionListener
{
int financeYears;
double interestRate;
int salary;
double loan;
double rate;
double yearlyPmt;
double[] monthlyPmt, principal, loanPmt, ratePmt, newPrincipal;
double endPrincipal;
boolean calculate = false;
boolean next = false;
boolean previous = false;
//variables
int yearNumber = 1;
int periodNumber = 1;
int month = 0;
int currMonth = 0;
double interestPerYear = 0;
DecimalFormat df = new DecimalFormat("###,###.00");
//layout preparation
LoanLayout customLayout = new LoanLayout();
JLabel loanLabel = new JLabel("Loan Amount");
JTextField loanText = new JTextField();
JLabel termLabel = new JLabel("Years Financed");
JTextField termText = new JTextField();
JLabel rateLabel = new JLabel("Interest Rate (x.xx)");
JTextField rateText = new JTextField();
JLabel salaryLabel = new JLabel("Annual Salary");
JTextField salaryText = new JTextField();
JLabel monthlyLabel = new JLabel("Monthly Payment");
JTextField monthlyText = new JTextField();
JLabel yearTotalLabel = new JLabel("Year Total");
JTextField yearTotalText = new JTextField();
JLabel salaryTaxLabel = new JLabel("Salary After Taxes");
JTextField salaryTaxText = new JTextField();
JLabel salPercentLabel = new JLabel("Salary Percent of Yearly Mortgage");
JTextField salPercentText = new JTextField();
JLabel scheduleLabel = new JLabel("Schedule");
JTextArea scheduleText = new JTextArea();
JScrollPane scroller = new JScrollPane(scheduleText);
public MortgageCalculator3()
{
JButton calcButton = new JButton("Calculate");
JButton resetButton = new JButton("Reset");
JButton scheduleButton = new JButton("Show Schedule");
JButton previousButton = new JButton("<< Previous Year");
JButton nextButton = new JButton("Next Year >>");
JButton exitButton = new JButton("Exit");
//add ActionListener to buttons
calcButton.addActionListener(this);
resetButton.addActionListener(this);
scheduleButton.addActionListener(this);
previousButton.addActionListener(this);
nextButton.addActionListener(this);
exitButton.addActionListener(this);
//add ActionCommand to buttons
calcButton.setActionCommand("calculate");
resetButton.setActionCommand("reset");
scheduleButton.setActionCommand("show");
previousButton.setActionCommand("previous");
nextButton.setActionCommand("next");
exitButton.setActionCommand("exit");
//getContentPane, set editable & setText for all labels, fields, and buttons
getContentPane().setLayout(customLayout);
getContentPane().add(loanLabel);
getContentPane().add(loanText);
getContentPane().add(termLabel);
getContentPane().add(termText);
getContentPane().add(rateLabel);
getContentPane().add(rateText);
getContentPane().add(salaryLabel);
getContentPane().add(salaryText);
getContentPane().add(calcButton);
getContentPane().add(resetButton);
getContentPane().add(monthlyLabel);
getContentPane().add(monthlyText);
monthlyText.setEditable(false);
getContentPane().add(yearTotalLabel);
getContentPane().add(yearTotalText);
yearTotalText.setEditable(false);
getContentPane().add(salaryTaxLabel);
getContentPane().add(salaryTaxText);
salaryTaxText.setEditable(false);
getContentPane().add(salPercentLabel);
getContentPane().add(salPercentText);
getContentPane().add(scheduleButton);
salPercentText.setEditable(false);
getContentPane().add(scheduleLabel);
getContentPane().add(scroller);
scheduleText.setEditable(false);
getContentPane().add(previousButton);
getContentPane().add(nextButton);
getContentPane().add(exitButton);
//added this to ensure that the Frame closes properly
addWindowListener(new WindowAdapter()
{
public void windowClosing(WindowEvent e)
{
System.exit(0);
}
}
);
}
//actionPerformed
public void actionPerformed(ActionEvent e)
{
String arg = e.getActionCommand();
if (arg == "calculate" )
{
scheduleText.setText("");
try
{
loan = Double.parseDouble(loanText.getText());
financeYears = Integer.parseInt(termText.getText());
rate = Double.parseDouble(rateText.getText());
salary = Integer.parseInt(salaryText.getText());
}
catch (Exception ex)
{
JOptionPane.showMessageDialog(null, "Invalid mortgage, term, rate, or salary amount\nFill out all above fields","Error", JOptionPane.ERROR_MESSAGE);
return;
}
calculate = true;
rate = rate / 100;
endPrincipal = loan;
DecimalFormat df1 = new DecimalFormat("###,###.000");
double[] monthlyPmt = new double[(int) (12 * financeYears + 1)];
double[] principal = new double[(int) (12 * financeYears + 1)];
for (int i = 0; i < monthlyPmt.length; i++)
{
principal[i] = loan;
monthlyPmt[i] = (double) Math.round((rate / 12 * principal[i] * (Math.pow(1 + rate / 12,financeYears * 12)))/(Math.pow((1 + rate / 12),financeYears * 12) -1) * 100) / 100;
yearlyPmt = (monthlyPmt[i] * 12);
}
int[] bracketRange = {0, 8375, 34000, 82400, 171850, 373650};
double[] taxBracket = {0.90, 0.85, 0.75, 0.72, 0.67, 0.65};
double afterTaxes = 0;
double salaryPercent = 0;
if (salary >= bracketRange[5])
{
salaryPercent = (yearlyPmt / (salary * taxBracket[5] / 100));
afterTaxes = salary * taxBracket[5];
}
if (salary >= bracketRange[4] && salary < bracketRange[5])
{
salaryPercent = (yearlyPmt / (salary * taxBracket[4] / 100));
afterTaxes = salary * taxBracket[4];
}
if (salary >= bracketRange[3] && salary < bracketRange[4])
{
salaryPercent = (yearlyPmt / (salary * taxBracket[3] / 100));
afterTaxes = salary * taxBracket[3];
}
if (salary >= bracketRange[2] && salary < bracketRange[3])
{
salaryPercent = (yearlyPmt / (salary * taxBracket[2] / 100));
afterTaxes = salary * taxBracket[2];
}
if (salary >= bracketRange[1] && salary < bracketRange[2])
{
salaryPercent = (yearlyPmt / (salary * taxBracket[1] / 100));
afterTaxes = salary * taxBracket[1];
}
if (salary >= bracketRange[0] && salary < bracketRange[1])
{
salaryPercent = (yearlyPmt / (salary * taxBracket[0] / 100));
afterTaxes = salary * taxBracket[0];
}
monthlyText.setText("$" + df.format(monthlyPmt[0]));
yearTotalText.setText("$" + df.format(yearlyPmt));
salaryTaxText.setText("$" + df.format(afterTaxes));
salPercentText.setText(df1.format(salaryPercent) + "%");
}
//if reset button is picked, fields are cleared.
if (arg == "reset")
{
calculate = false;
loanText.setText("");
termText.setText("");
rateText.setText("");
salaryText.setText("");
monthlyText.setText("");
yearTotalText.setText("");
salaryTaxText.setText("");
salPercentText.setText("");
scheduleText.setText("");
yearNumber = 1;
}
//if show button is picked, year 1 is shown in the schedule area
if (arg == "show")
{
if (calculate)
{
createSchedule(monthlyPmt, principal, financeYears, rate);
interestPerYear = 0;
yearNumber = 1;
populateSchedule(yearNumber);
}
}
//if previous button is picked, schedule goes back 1 year
if (arg == "previous")
{
previous = true;
if (yearNumber > 1)
{
yearNumber = yearNumber - 1;
populateSchedule(yearNumber);
}
else
JOptionPane.showMessageDialog(null, "Cannot go back, already on Year 1","Error", JOptionPane.ERROR_MESSAGE);
}
//if next button is picked, schedule goes forward 1 year
if (arg == "next")
{
next = true;
if (yearNumber < financeYears)
{
yearNumber = yearNumber + 1;
populateSchedule(yearNumber);
}
else
JOptionPane.showMessageDialog(null, "Cannot continue forward, reached maximum year","Error", JOptionPane.ERROR_MESSAGE);
}
//if exit button is picked, program closes
if (arg == "exit")
{
System.exit(0);
}
}
public static void main(String[] args)
{
//creating the JFrame window
{
new MortgageCalculator3();
JFrame nFrame = new MortgageCalculator3();
nFrame.setVisible(true);
nFrame.setTitle("Mortgage Calculator");
nFrame.setSize(650,770);
nFrame.setLocation(600,200);
}
}
public void createSchedule(double monthlyPmt[], double principal[], double financeYears, double rate)
{
double[] loanPmt = new double[(int) (12 * financeYears + 1)];
double[] ratePmt = new double[(int) (12 * financeYears + 1)];
double[] newPrincipal = new double[(int) (12 * financeYears + 1)];
for (yearNumber = 1; yearNumber <= financeYears; yearNumber++)
{
for (int periodNumber = 1; periodNumber <= 12; periodNumber++)
{
month = (12 * (yearNumber - 1)) + periodNumber - 1;
ratePmt[month] = (double) Math.round((principal[month] * rate / 12) * 100) / 100;
loanPmt[month] = (double) Math.round((monthlyPmt[month] - ratePmt[month]) * 100) / 100;
newPrincipal[month] = (double) Math.round((principal[month] - loanPmt[month]) * 100) / 100;
principal[month + 1] = newPrincipal[month];
}
principal[month + 1] = newPrincipal[month];
}
}
public void populateSchedule(int yearNumber) // Places the values for a given year of the loan into the schedule
{
if (yearNumber >= 10)
scheduleText.append("\t\t Year " + yearNumber + "\n\t\t ********");
else
scheduleText.append("\t\t Year " + yearNumber + "\n\t\t *******");
scheduleText.append("\nMONTH\tBEG BALANCE\tLOAN\tRATE\tTOTAL\tEND BALANCE");
for (int periodNumber = 1; periodNumber <= 12; periodNumber++)
{
currMonth = 12 * (yearNumber - 1) + periodNumber - 1;
//for last few payments, so the balance doesn't go in the negative
if (newPrincipal[currMonth] < 0)
{
newPrincipal[currMonth] = 0;
loanPmt[currMonth] = principal[currMonth] - ratePmt[currMonth];
monthlyPmt[currMonth] = loanPmt[currMonth] + ratePmt[currMonth];
}
scheduleText.append("\n" + (currMonth + 1) + "\t$" + (df.format(principal[currMonth])) + " \t$" + (df.format(loanPmt[currMonth])) + "\t$" + (df.format(ratePmt[currMonth])) + "\t$" + (df.format(monthlyPmt[currMonth])) + "\t$" + (df.format(newPrincipal[currMonth])));
principal[currMonth + 1] = newPrincipal[currMonth];
if (yearNumber <= financeYears)
interestPerYear += ratePmt[currMonth];
}
if (yearNumber < financeYears)
scheduleText.append("\n\nTotal interest paid so far is: $" + df.format(interestPerYear));
else
{
scheduleText.append("\n\nTotal interest paid: $" + df.format(interestPerYear));
scheduleText.append("\nTotal cost of home: $" + df.format(endPrincipal + interestPerYear) + " after " + (yearNumber) + " years");
}
scheduleText.append("\n\n");
}
//Layout manager
class LoanLayout implements LayoutManager
{
public LoanLayout()
{
}
public void addLayoutComponent(String name, Component comp)
{
}
public void removeLayoutComponent(Component comp)
{
}
// layout dimensions
public Dimension preferredLayoutSize(Container parent)
{
Dimension dim = new Dimension(0, 0);
Insets insets = parent.getInsets();
dim.height = 770 + insets.top + insets.bottom; //height of window
dim.width = 650 + insets.left + insets.right; // width of window
return dim;
}
public Dimension minimumLayoutSize(Container parent)
{
Dimension dim = new Dimension(0, 0);
return dim;
}
// arrangement of all components (JButton, JTextField, and JLabel) in window as listed above
public void layoutContainer(Container parent)
{
Insets insets = parent.getInsets();
Component w; // array for components (JButton, JTextField, and JLabel)
w = parent.getComponent(0);
if (w.isVisible()) {w.setBounds(insets.left+20,insets.top+20,130,20);} //loan label
w = parent.getComponent(1);
if (w.isVisible()) {w.setBounds(insets.left+170,insets.top+20,100,20);} // loan field
w = parent.getComponent(2);
if (w.isVisible()) {w.setBounds(insets.left+20,insets.top+50,130,20);} // term label
w = parent.getComponent(3);
if (w.isVisible()) {w.setBounds(insets.left+170,insets.top+50,100,20);} // term field
w = parent.getComponent(4);
if (w.isVisible()) {w.setBounds(insets.left+20,insets.top+80,130,20);} // rate label
w = parent.getComponent(5);
if (w.isVisible()) {w.setBounds(insets.left+170,insets.top+80,100,20);} // rate field
w = parent.getComponent(6);
if (w.isVisible()) {w.setBounds(insets.left+20,insets.top+110,160,20);} // salary label
w = parent.getComponent(7);
if (w.isVisible()) {w.setBounds(insets.left+170,insets.top+110,100,20);} // salary field
w = parent.getComponent(8);
if (w.isVisible()) {w.setBounds(insets.left+20,insets.top+150,120,30);} // calculate button
w = parent.getComponent(9);
if (w.isVisible()) {w.setBounds(insets.left+150,insets.top+150,100,30);} // reset button
w = parent.getComponent(10);
if (w.isVisible()) {w.setBounds(insets.left+20,insets.top+200,140,20);} // payment label
w = parent.getComponent(11);
if (w.isVisible()) {w.setBounds(insets.left+170,insets.top+200,100,20);} // payment field
w = parent.getComponent(12);
if (w.isVisible()) {w.setBounds(insets.left+20,insets.top+230,140,20);} // yearTotal label
w = parent.getComponent(13);
if (w.isVisible()) {w.setBounds(insets.left+170,insets.top+230,100,20);} // yearTotal field
w = parent.getComponent(14);
if (w.isVisible()) {w.setBounds(insets.left+20,insets.top+260,140,20);} // salaryTax label
w = parent.getComponent(15);
if (w.isVisible()) {w.setBounds(insets.left+170,insets.top+260,100,20);} // salaryTax field
w = parent.getComponent(16);
if (w.isVisible()) {w.setBounds(insets.left+20,insets.top+290,210,20);} // salPercent label
w = parent.getComponent(17);
if (w.isVisible()) {w.setBounds(insets.left+240,insets.top+290,80,20);} // salPercent field
w = parent.getComponent(18);
if (w.isVisible()) {w.setBounds(insets.left+20,insets.top+320,200,30);} // show button
w = parent.getComponent(19);
if (w.isVisible()) {w.setBounds(insets.left+285,insets.top+340,80,20);} // schedule label
w = parent.getComponent(20);
if (w.isVisible()) {w.setBounds(insets.left+20,insets.top+370,610,300);} // schedule field
w = parent.getComponent(21);
if (w.isVisible()) {w.setBounds(insets.left+20,insets.top+680,150,30);} // previous button
w = parent.getComponent(22);
if (w.isVisible()) {w.setBounds(insets.left+480,insets.top+680,150,30);} // next button
w = parent.getComponent(23);
if (w.isVisible()) {w.setBounds(insets.left+285,insets.top+690,80,50);} // exit button
}
}
}
Now, at the very beginning is where i called out double[] arrays,
double[] monthlyPmt, principal, loanPmt, ratePmt, newPrincipal;
then when I press the "calculate" button, I called out or initialize 2 of them, telling it how many elements in the array I want, then assigning numbers to the elements, etc.
public void actionPerformed(ActionEvent e)
{
String arg = e.getActionCommand();
if (arg == "calculate" )
{
scheduleText.setText("");
try
{
loan = Double.parseDouble(loanText.getText());
financeYears = Integer.parseInt(termText.getText());
rate = Double.parseDouble(rateText.getText());
salary = Integer.parseInt(salaryText.getText());
}
catch (Exception ex)
{
JOptionPane.showMessageDialog(null, "Invalid mortgage, term, rate, or salary amount\nFill out all above fields","Error", JOptionPane.ERROR_MESSAGE);
return;
}
calculate = true;
rate = rate / 100;
endPrincipal = loan;
DecimalFormat df1 = new DecimalFormat("###,###.000");
double[] monthlyPmt = new double[(int) (12 * financeYears + 1)];
double[] principal = new double[(int) (12 * financeYears + 1)];
for (int i = 0; i < monthlyPmt.length; i++)
{
principal[i] = loan;
monthlyPmt[i] = (double) Math.round((rate / 12 * principal[i] * (Math.pow(1 + rate / 12,financeYears * 12)))/(Math.pow((1 + rate / 12),financeYears * 12) -1) * 100) / 100;
yearlyPmt = (monthlyPmt[i] * 12);
}
now to look more closer in this code
double[] monthlyPmt = new double[(int) (12 * financeYears + 1)];
double[] principal = new double[(int) (12 * financeYears + 1)];
for (int i = 0; i < monthlyPmt.length; i++)
{
principal[i] = loan;
monthlyPmt[i] = (double) Math.round((rate / 12 * principal[i] * (Math.pow(1 + rate / 12,financeYears * 12)))/(Math.pow((1 + rate / 12),financeYears * 12) -1) * 100) / 100;
yearlyPmt = (monthlyPmt[i] * 12);
}
right there is where I do all the things I explained....now, later on in the code, I call this...
if (arg == "show")
{
if (calculate)
{
createSchedule(monthlyPmt, principal, financeYears, rate);
interestPerYear = 0;
yearNumber = 1;
populateSchedule(yearNumber);
}
}
Which for some reason, even though I have already assigned numbers to the arrays, with however many elements total there are according to what the user wants, I think it still thinks I'm requesting THIS
double[] monthlyPmt, principal, loanPmt, ratePmt, newPrincipal;
Which is null to begin with, that's why I initialize them in the "calculate" button.
First off, I thought arrays REMEMBER what happens, what is assigned to it, etc, how come for some reason, it's telling me on line 309
public void createSchedule(double monthlyPmt[], double principal[], double financeYears, double rate)
{
double[] loanPmt = new double[(int) (12 * financeYears + 1)];
double[] ratePmt = new double[(int) (12 * financeYears + 1)];
double[] newPrincipal = new double[(int) (12 * financeYears + 1)];
for (yearNumber = 1; yearNumber <= financeYears; yearNumber++)
{
for (int periodNumber = 1; periodNumber <= 12; periodNumber++)
{
month = (12 * (yearNumber - 1)) + periodNumber - 1;
ratePmt[month] = (double) Math.round((principal[month] * rate / 12) * 100) / 100;
loanPmt[month] = (double) Math.round((monthlyPmt[month] - ratePmt[month]) * 100) / 100;
newPrincipal[month] = (double) Math.round((principal[month] - loanPmt[month]) * 100) / 100;
principal[month + 1] = newPrincipal[month];
}
principal[month + 1] = newPrincipal[month];
}
}
309 is the
ratePmt[month] = (double) Math.round((principal[month] * rate / 12) * 100) / 100;
telling me that principal[month] is NULL???? it shouldnt be because I told it what I want from it, from
double[] monthlyPmt = new double[(int) (12 * financeYears + 1)];
double[] principal = new double[(int) (12 * financeYears + 1)];
And I'm sure that if the principal[month] problem is fixed, it will tell me monthlyPmt[month] is ALSO NULL.
Basically I just need my arrays to be program-wide for everything to read them correctly.
Again, I've been spending 9 days, since LAST wednesday on this very problem. Somebody help me....