I would like to be able to divide this java code up into more than one file, so I can reuse the code for other programs, but I'm not sure what I can grab.

Right now, I can't make another program using this code, as you see the WHOLE program is in this file alone, what can I do?

package usefulapps;
/*  
    File: MortgageCalculator3.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.text.SimpleDateFormat;
import java.util.Date;
											

@SuppressWarnings("serial")
public class MortgageCalculator3 extends JFrame implements ActionListener
{
	// Getting the year, then parsing it so I can manipulate it as an integer
	Date thisYear = new Date();
	SimpleDateFormat formatter = new SimpleDateFormat("yyyy");
	String y = formatter.format(thisYear);
	int getYear = Integer.parseInt(y);
	//*******
	int financeYears;
	double interestRate;
    int salary;
    double loan;
    double rate;
    double yearlyPmt;
    double[] monthlyPmt, principal, loanPmt, ratePmt, newPrincipal, interestPerYear;
    double interest;
	double endPrincipal;
	boolean calculate = false;
	boolean next = false;
	boolean previous = false;
	//variables
	int yearNumber;
	int periodNumber = 1;
	int month = 0;
	int currMonth = 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
		Container pane = getContentPane();
		pane.setLayout(customLayout);
		pane.add(loanLabel);
		pane.add(loanText);
		pane.add(termLabel);
		pane.add(termText);
		pane.add(rateLabel);
		pane.add(rateText);
		pane.add(salaryLabel);
		pane.add(salaryText);
		pane.add(calcButton);
		pane.add(resetButton);
		pane.add(monthlyLabel);
		pane.add(monthlyText);
		monthlyText.setEditable(false);
		pane.add(yearTotalLabel);
		pane.add(yearTotalText);
		yearTotalText.setEditable(false);
		pane.add(salaryTaxLabel);
		pane.add(salaryTaxText);
		salaryTaxText.setEditable(false);
		pane.add(salPercentLabel);
		pane.add(salPercentText);
		pane.add(scheduleButton);
		salPercentText.setEditable(false);
		pane.add(scheduleLabel);
		pane.add(scroller);
		scheduleText.setEditable(false);
		pane.add(previousButton);
		pane.add(nextButton);
		pane.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" ) 
		{
			if (next)
				getYear = getYear - yearNumber + 1;
			next = false;
			interest = 0;
			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");
		    
		    monthlyPmt = new double[(int) (12 * financeYears + 1)];
		    principal = new double[(int) (12 * financeYears + 1)];
		    interestPerYear = new double[financeYears];
		    
	    	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};		//10%, 15%, 25%, 28%, 33%, 35%
			double afterTaxes = 0;
			double salaryPercent = 0;
			if (salary >= bracketRange[5])
			{
				salaryPercent = (yearlyPmt / (salary * taxBracket[5] / 100));
				afterTaxes = salary * taxBracket[5];
			}
			for (int x = 4, y = 5; x > -1 && y > 0; x--, y--)
			{
				if (salary >= bracketRange[x] && salary < bracketRange[y])
				{
					salaryPercent = (yearlyPmt / (salary * taxBracket[x] / 100));
					afterTaxes = salary * taxBracket[x];
				}
			}
		   
			monthlyText.setText("$" + df.format(monthlyPmt[0]));
	        yearTotalText.setText("$" + df.format(yearlyPmt));
	        salaryTaxText.setText("$" + df.format(afterTaxes));
	        salPercentText.setText(df1.format(salaryPercent) + "%");
	        
	        createSchedule(monthlyPmt, principal, financeYears, rate);
	    }
		//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("");
		}
		//if show button is picked, year 1 is shown in the schedule area
		if (arg == "show")
		{
			if (calculate)
			{
				yearNumber = 1;
				populateSchedule(yearNumber);
			}
			calculate = false;
		}
		//if previous button is picked, schedule goes back 1 year
		if (arg == "previous")
		{
			previous = true;
			if (yearNumber > 1)
			{
				yearNumber--;
				getYear--;
				populateSchedule(yearNumber);
			}	
		}
		//if next button is picked, schedule goes forward 1 year
		if (arg == "next")
		{
			next = true;
			if (yearNumber < financeYears) 
			{
				yearNumber++;
				getYear++;
				populateSchedule(yearNumber);
			}
		}
		//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)
	{	
		loanPmt = new double[(int) (12 * financeYears + 1)];
		ratePmt = new double[(int) (12 * financeYears + 1)];
		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];
				interest += ratePmt[month];
			}
			principal[month + 1] = newPrincipal[month];
			interestPerYear[yearNumber - 1] = interest;
		}
	}
	public void populateSchedule(int yearNumber)  // Places the values for a given year of the loan into the schedule
	{
		if (yearNumber >= 10)
			scheduleText.setText("\t\t             Year " + yearNumber + " - " + getYear + "\n\t\t                   ********");
		else
			scheduleText.setText("\t\t              Year " + yearNumber + " - " + getYear + "\n\t\t                   ********");
		scheduleText.append("\nMONTH\tBEG BALANCE\tLOAN\tINTEREST\tPAYMENT\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)
			scheduleText.append("\n\nTotal interest paid so far is: $" + df.format(interestPerYear[yearNumber - 1]));
		else
		{
			scheduleText.append("\n\nTotal interest paid: $" + df.format(interestPerYear[yearNumber - 1]));
			scheduleText.append("\nTotal cost of home: $" + df.format(endPrincipal + interestPerYear[yearNumber - 1]) + " after " + (yearNumber) + " years");
		}
	}
	//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 = parent.getComponent(0); // array for components (JButton, JTextField, and JLabel)
			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
		}
	}
}

Recommended Answers

All 14 Replies

create different classes

Separate the mortgage logic & calculations from the user interface. Put them in their own class, with its own variables, and provide public methods that the user interface can call to set the variables and get the calculated mortgage figures.
Now you have 2 classes; put each one in its own file.

Separate the mortgage logic & calculations from the user interface. Put them in their own class, with its own variables, and provide public methods that the user interface can call to set the variables and get the calculated mortgage figures.
Now you have 2 classes; put each one in its own file.

There's a couple user interfaces, I'm not sure which you are talking about. I have done java for only 2 1/2 years, I'm not fully understanding what you mean by all you said. Could you possibly copy and paste, letting me know what is what?

It's up to you whether you separate your 2 user interfaces into 2 separate classes. The main thing to do is to extract all the mortgage-related variables and logic into their own class that is independent of any UI, then use that as a service that the UI or UIs can call.
Google MVC (model, view, controller) - you will be doing a simplified version with a model and a UI that combines the view and the controller. Or look at how classes like JTable separate the user interface from the underlying data.

I sorta understand what you are telling me.....how about giving me an example with my code? I can't understand it unless I can see it. What I do understand is separating parts, but I've only been doing java for 2 1/2 years, I've never separated code before into their own independent files before, only dependent files, which end up only working with another...I couldn't figure it out.

Do I take this

//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
		Container pane = getContentPane();
		pane.setLayout(customLayout);
		pane.add(loanLabel);
		pane.add(loanText);
		pane.add(termLabel);
		pane.add(termText);
		pane.add(rateLabel);
		pane.add(rateText);
		pane.add(salaryLabel);
		pane.add(salaryText);
		pane.add(calcButton);
		pane.add(resetButton);
		pane.add(monthlyLabel);
		pane.add(monthlyText);
		monthlyText.setEditable(false);
		pane.add(yearTotalLabel);
		pane.add(yearTotalText);
		yearTotalText.setEditable(false);
		pane.add(salaryTaxLabel);
		pane.add(salaryTaxText);
		salaryTaxText.setEditable(false);
		pane.add(salPercentLabel);
		pane.add(salPercentText);
		pane.add(scheduleButton);
		salPercentText.setEditable(false);
		pane.add(scheduleLabel);
		pane.add(scroller);
		scheduleText.setEditable(false);
		pane.add(previousButton);
		pane.add(nextButton);
		pane.add(exitButton);
 
		//added this to ensure that the Frame closes properly	
		addWindowListener(new WindowAdapter()
			{
				public void windowClosing(WindowEvent e)
				{	
					System.exit(0);
				}
			}
			);
	}

And this

//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 = parent.getComponent(0); // array for components (JButton, JTextField, and JLabel)
			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
		}
	}
}

Into their own separate files? And once I do that, how do I link them to the rest of it, which seems like only the mortgage calcs and variables?

Your mortgage class will probably have methods something like:
setTerm(int years), setInterestRate(float rate), setAmount(int dollars) etc etc
and others like:
float[] getMonthlyPayments() // returns an array, one element per month
float getTotalInterest()

So in your GUI you create an instance of that class, then use the set methods, as in
setInterestRate(Float.parseFloat(rateText.getText());
finally, when the user presses the Calc button(s) you can call the get methods to get the values to display in the GUI.

In terms of dependent/independent files/classes, the goal is that the mortgage class should not depend on the GUI - after all the calculation of a mortgage does not depend in any way on how the user happened to enter to data. But the GUI class(es) will depend on the mortgage class to do the calculations for them.
It's a one-way dependency, which is a far better architecture than two-way dependencies because the interactions between the classes are easier to understand and control. It also allows for re-use - for example if you wrote a web-based mortgage system, you could use exactly the same mortgage calculation class without any modifications, only the UI classes would be replaced.

I would like to know what I am doing wrong. It took me a few hours, with Eclipse helping me out with some things. Here's the GUI or UI code.

//Date: 10/4/2010

package usefulapps;

import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Insets;
import java.awt.LayoutManager;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.Date;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;

@SuppressWarnings("serial")
public class MortgageCalculatorGUI extends JFrame implements ActionListener
{
	// Getting the year, then parsing it so I can manipulate it as an integer
	Date thisYear = new Date();
	SimpleDateFormat formatter = new SimpleDateFormat("yyyy");
	String y = formatter.format(thisYear);
	int getYear = Integer.parseInt(y);
	//*******
	boolean calculate = false;
	boolean next = false;
	boolean previous = false;
	DecimalFormat df = new DecimalFormat("###,###.00");
	DecimalFormat df1 = new DecimalFormat("###,###.000");
	
	MortgageCalculator4 mc4 = new MortgageCalculator4();
	
	//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");
		
			static JTextArea scheduleText = new JTextArea();
			
			JScrollPane scroller = new JScrollPane(scheduleText);
			
	public MortgageCalculatorGUI()
	{
		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
		Container pane = getContentPane();
		pane.setLayout(customLayout);
		pane.add(loanLabel);
		pane.add(loanText);
		pane.add(termLabel);
		pane.add(termText);
		pane.add(rateLabel);
		pane.add(rateText);
		pane.add(salaryLabel);
		pane.add(salaryText);
		pane.add(calcButton);
		pane.add(resetButton);
		pane.add(monthlyLabel);
		pane.add(monthlyText);
		monthlyText.setEditable(false);
		pane.add(yearTotalLabel);
		pane.add(yearTotalText);
		yearTotalText.setEditable(false);
		pane.add(salaryTaxLabel);
		pane.add(salaryTaxText);
		salaryTaxText.setEditable(false);
		pane.add(salPercentLabel);
		pane.add(salPercentText);
		pane.add(scheduleButton);
		salPercentText.setEditable(false);
		pane.add(scheduleLabel);
		pane.add(scroller);
		scheduleText.setEditable(false);
		pane.add(previousButton);
		pane.add(nextButton);
		pane.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 action = e.getActionCommand();
		if (action == "calculate" ) 
		{
			if (next)
				getYear = getYear - mc4.getYearNumber() + 1;
			next = false;
			scheduleText.setText("");
			
		    try 
		    {
	    		mc4.setLoan(Double.parseDouble(loanText.getText()));
	    		mc4.setFinanceYears(Integer.parseInt(termText.getText()));
	    		mc4.setRate(Double.parseDouble(rateText.getText()));
	    		mc4.setSalary(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;
		   
			monthlyText.setText("$" + df.format(mc4.getMonthlyPmt()));
	        yearTotalText.setText("$" + df.format(mc4.getYearlyPmt()));
	        salaryTaxText.setText("$" + df.format(mc4.getAfterTaxes()));
	        salPercentText.setText(df1.format(mc4.getSalaryPercent()) + "%");
	        
	        
	    }
		//if reset button is picked, fields are cleared.
		if (action == "reset")
		{
			calculate = false;
			loanText.setText("");
			termText.setText("");
			rateText.setText("");
			salaryText.setText("");
			monthlyText.setText("");
			yearTotalText.setText("");
			salaryTaxText.setText("");
			salPercentText.setText("");
			scheduleText.setText("");
		}
		//if show button is picked, year 1 is shown in the schedule area
		if (action == "show")
		{
			if (calculate)
			{
				mc4.yearNumber = 1;
				firstPopulate();
				mc4.populateSchedule(mc4.yearNumber);
			}
			calculate = false;
		}
		//if previous button is picked, schedule goes back 1 year
		if (action == "previous")
		{
			previous = true;
			if (mc4.getYearNumber() > 1)
			{
				mc4.yearNumber--;
				getYear--;
				firstPopulate();
				mc4.populateSchedule(mc4.getYearNumber());
			}	
		}
		//if next button is picked, schedule goes forward 1 year
		if (action == "next")
		{
			next = true;
			if (mc4.getYearNumber() < mc4.getFinanceYears()) 
			{
				mc4.yearNumber++;
				getYear++;
				firstPopulate();
				mc4.populateSchedule(mc4.getYearNumber());
			}
		}
		//if exit button is picked, program closes
		if (action == "exit")
		{
			System.exit(0);
		}
		
	}
	
	public void firstPopulate()
	{
		if (mc4.getYearNumber() >= 10)
			scheduleText.setText("\t\t             Year " + mc4.getYearNumber() + " - " + getYear + "\n\t\t                   ********");
		else
			scheduleText.setText("\t\t              Year " + mc4.getYearNumber() + " - " + getYear + "\n\t\t                   ********");
		scheduleText.append("\nMONTH\tBEG BALANCE\tLOAN\tINTEREST\tPAYMENT\tEND BALANCE");
	}
	
	
	
	public static void main(String[] args)						
	{																					
		//creating the JFrame window
		{ 
			new MortgageCalculator4();
			MortgageCalculator4 nFrame = new MortgageCalculator4();
			nFrame.setVisible(true);
			nFrame.setTitle("Mortgage Calculator");
			nFrame.setSize(650,770);
			nFrame.setLocation(600,200);
		}
	}
	
	//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 = parent.getComponent(0); // array for components (JButton, JTextField, and JLabel)
			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
		}
	}
}

And here is the Mortgage code.

//Date: started continuing for Danny on 4/28/2010, finished on 5/8/2010

package usefulapps;
/*  
    File: MortgageCalculator3.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.text.SimpleDateFormat;
import java.util.Date;
											

@SuppressWarnings("serial")
public class MortgageCalculator4
{
	MortgageCalculatorGUI mcGUI = new MortgageCalculatorGUI();
	
	public void setLoan(double loanAmt)
	{
		loan = loanAmt;
	}
	public void setFinanceYears(int years)
	{
		financeYears = years;
	}
	public int getFinanceYears()
	{
		return financeYears;
	}
	public void setRate(double interestAmt)
	{
		rate = interestAmt;
	}
	public void setSalary(int salaryAmt)
	{
		salary = salaryAmt;
	}
	public int getYearNumber()
	{
		return yearNumber;
	}
	public double[] getMonthlyPmt()
	{
		return monthlyPmt;
	}
	public double getYearlyPmt()
	{
		return yearlyPmt;
	}
	public double getAfterTaxes()
	{
		return afterTaxes;
	}
	public double getSalaryPercent()
	{
		return salaryPercent;
	}
	static int financeYears;
    int salary;
    double loan;
    double rate;
    double yearlyPmt;
    static double[] monthlyPmt;
	static double[] principal;
	static double[] loanPmt;
	static double[] ratePmt;
	static double[] newPrincipal;
	static double[] interestPerYear;
    double interest;
	static double endPrincipal;
	//variables
	int yearNumber;
	int periodNumber = 1;
	int month = 0;
	static int currMonth = 0;
	static DecimalFormat df = new DecimalFormat("###,###.00");
	double afterTaxes = 0;
	double salaryPercent = 0;
	
	public void calculations(double loan, int financeYears, double rate, int salary)
	{
		rate = rate / 100;
	    endPrincipal = loan;
	    
	    monthlyPmt = new double[(int) (12 * financeYears + 1)];
	    principal = new double[(int) (12 * financeYears + 1)];
	    interestPerYear = new double[financeYears];
	    
    	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};		//10%, 15%, 25%, 28%, 33%, 35%
	
		if (salary >= bracketRange[5])
		{
			salaryPercent = (yearlyPmt / (salary * taxBracket[5] / 100));
			afterTaxes = salary * taxBracket[5];
		}
		for (int x = 4, y = 5; x > -1 && y > 0; x--, y--)
		{
			if (salary >= bracketRange[x] && salary < bracketRange[y])
			{
				salaryPercent = (yearlyPmt / (salary * taxBracket[x] / 100));
				afterTaxes = salary * taxBracket[x];
			}
		}
	}
	public void createSchedule(double monthlyPmt[], double principal[], double financeYears, double rate)
	{	
		loanPmt = new double[(int) (12 * financeYears + 1)];
		ratePmt = new double[(int) (12 * financeYears + 1)];
		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];
				interest += ratePmt[month];
			}
			principal[month + 1] = newPrincipal[month];
			interestPerYear[yearNumber - 1] = interest;
		}
	}
	public static void populateSchedule(int yearNumber)  // Places the values for a given year of the loan into the schedule
	{
		
		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];
			}
			MortgageCalculatorGUI.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)
			MortgageCalculatorGUI.scheduleText.append("\n\nTotal interest paid so far is: $" + df.format(interestPerYear[yearNumber - 1]));
		else
		{
			MortgageCalculatorGUI.scheduleText.append("\n\nTotal interest paid: $" + df.format(interestPerYear[yearNumber - 1]));
			MortgageCalculatorGUI.scheduleText.append("\nTotal cost of home: $" + df.format(endPrincipal + interestPerYear[yearNumber - 1]) + " after " + (yearNumber) + " years");
		}
	}
	public void setVisible(boolean b) {
		// TODO Auto-generated method stub
		
	}
	public void setTitle(String string) {
		// TODO Auto-generated method stub
		
	}
	public void setSize(int i, int j) {
		// TODO Auto-generated method stub
		
	}
	public void setLocation(int i, int j) {
		// TODO Auto-generated method stub
		
	}
	
	
}

I would like to know what I am doing wrong.

I took a very quick look and nothing jumped out at me.
Exactly what problems are you having, exactly.

Exception in thread "main" java.lang.StackOverflowError
at apple.awt.CGraphicsConfig.getBounds(Native Method)
at apple.awt.CGraphicsConfig.getBounds(CGraphicsConfig.java:258)
at java.awt.Window.init(Window.java:394)
at java.awt.Window.<init>(Window.java:433)
at java.awt.Frame.<init>(Frame.java:403)
at java.awt.Frame.<init>(Frame.java:368)
at javax.swing.JFrame.<init>(JFrame.java:158)
at usefulapps.MortgageCalculatorGUI.<init>(MortgageCalculatorGUI.java:84)
at usefulapps.MortgageCalculator4.<init>(MortgageCalculator4.java:20)
at usefulapps.MortgageCalculatorGUI.<init>(MortgageCalculatorGUI.java:41)
at usefulapps.MortgageCalculator4.<init>(MortgageCalculator4.java:20)
at usefulapps.MortgageCalculatorGUI.<init>(MortgageCalculatorGUI.java:41)
at usefulapps.MortgageCalculator4.<init>(MortgageCalculator4.java:20)


A LOT of lines, over 200 lines, of the above last 2 lines


I've never separated two programs before to allow one of them to be independent and the other to be dependent. So this is all new to me.

at usefulapps.MortgageCalculatorGUI.<init>(MortgageCalculatorGUI.java:41)
at usefulapps.MortgageCalculator4.<init>(MortgageCalculator4.java:20)
at usefulapps.MortgageCalculatorGUI.<init>(MortgageCalculatorGUI.java:41)
at usefulapps.MortgageCalculator4.<init>(MortgageCalculator4.java:20)

Looks like MortgageCalculatorGUI's constructor is creating a new instance of MortgageCalculator4, which is what I would expect, BUT the constructor for MortgageCalculator4 seems to try to create a new instance of MortgageCalculatorGUI, which is absolutely wrong, and causes an infinite loop.
MortgageCalculator4 should have NO hard-wired references to any poart of the GUI.

Ok, so I fixed that, but now when I try to execute the program, it closes as soon as it opens, showing no window, nothing, like a premature exit execution.

any suggestions? I'm still stuck, again I have never linked two programs in this complexity before. Please help.

I actually figured it out!! Thanks for all your help, JamesCherrill

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.