I created the GUI to display the monthly mortgage payment for any loan principle at a specific term and rate. The GUI works fine but I have some improvements I can't seem to figure out and I need to display an amortization table.
Issue# 1: I am usure how to put the amortization table in the GUI or in a JOptionPane. I have tried several ways to get it in the pane. I got it to display one month at a time on way and then to display a wrong amount several other ways. Here is the code for the amortization table but it is not in my GUI code.
RemainingBalance = PrincipleAmount;
// Output header amortization here
System.out.println("Month Remaining Balance Interest Paid Payment Amount");
// THE NEXT PART IS THE AMORITIZATION TABLE
//THE "for" MEANS IT IS A LOOP THAT WILL CONTINUE UNTIL "i <= 360"
for (int i = 1; i <= 360; i++)
{
MonthlyInterestAmount = RemainingBalance * MonthlyInterestRate;
RemainingBalance = RemainingBalance - (MonthlyPayment - MonthlyInterestAmount);
sRemainingBalance = currency.format(RemainingBalance);
sMonthlyInterestAmount = currency.format(MonthlyInterestAmount);
String AmortizationOutput = String.format
("%,3d $%,10.2f " + "$%,8.2f $%,8.2f",
i, RemainingBalance, MonthlyInterestAmount, MonthlyPayment);
System.out.println(AmortizationOutput);
}
The next issues are improvements
Issue#2: the reset button should clear the entry, return the curser to the InputPrincipleAmt text field, and unselect any radio button. Currently it clears the input but nothing else.
Issue#3: InputPrincipleAmtValidateAmt section should display an error message when the focus is lost, when user click "ok" on the message-it should clear the entry, return the curser to the InputPrincipleAmt text field, and unselect any radio button.
Currently it clears the input but nothing else.
Issue#4: Calculate button-- If the user inputs a good amount and selects a term and rate, the button will display the monthly payment (and the amortization table mentioned earlier). if the user inputs a bad amount, it should display an error message and when the user clicks ok it should clear the entry, return the curser to the InputPrincipleAmt text field, and unselect any radio button. currently: if the user inputs a bad amount and hits calculate without selecting a rate, the error message displays twice . the user hits ok on both and it clears the input but nothing else. if they do select a rate and then ok on the error message from the input field, the fields should clear and radio button should unselect, and the cursor should return to the input field.
here is my code:
package bowen.week.pkg2;
import java.text.NumberFormat;
import javax.swing.JOptionPane;
/**
*
* @author Joey
*/
public class JoeyWeek3b extends javax.swing.JFrame {
/**
* Creates new form JoeyWeek3b
*/
public JoeyWeek3b() {
initComponents();
}
/**
* This method is called from within the constructor to initialize the form.
* WARNING: Do NOT modify this code. The content of this method is always
* regenerated by the Form Editor.
*/
// Begin generated code that cannot be edited in the source code
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">
private void initComponents() {
buttonGroup1 = new javax.swing.ButtonGroup();
jLabel1 = new javax.swing.JLabel();
ResetButton = new javax.swing.JButton();
year7rate535 = new javax.swing.JRadioButton();
InputPrincipleAmt = new javax.swing.JTextField();
PrincipleLabel = new javax.swing.JLabel();
OutputMonthlyPayment = new javax.swing.JTextField();
year15rate550 = new javax.swing.JRadioButton();
ExitButton = new javax.swing.JButton();
year30rate575 = new javax.swing.JRadioButton();
jSeparator1 = new javax.swing.JSeparator();
CalcHead = new javax.swing.JLabel();
MonthlyPmtLabel = new javax.swing.JLabel();
CalcButton = new javax.swing.JButton();
setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
jLabel1.setText("$");
ResetButton.setFont(new java.awt.Font("Times New Roman", 1, 18)); // NOI18N
ResetButton.setText("Reset");
ResetButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
ResetButtonActionPerformed(evt);
}
});
buttonGroup1.add(year7rate535);
year7rate535.setText("7 years at 5.35% APR");
InputPrincipleAmt.setFont(new java.awt.Font("Times New Roman", 1, 18)); // NOI18N
InputPrincipleAmt.setToolTipText("Only enter whole numbers.. Example --200000");
InputPrincipleAmt.addFocusListener(new java.awt.event.FocusAdapter() {
public void focusLost(java.awt.event.FocusEvent evt) {
InputPrincipleAmtValidateAmt(evt);
}
});
PrincipleLabel.setFont(new java.awt.Font("Times New Roman", 1, 18)); // NOI18N
PrincipleLabel.setText("Principle Amount:");
OutputMonthlyPayment.setEditable(false);
OutputMonthlyPayment.setFont(new java.awt.Font("Times New Roman", 1, 18)); // NOI18N
OutputMonthlyPayment.setToolTipText("");
OutputMonthlyPayment.setFocusable(false);
buttonGroup1.add(year15rate550);
year15rate550.setText("15 years at 5.50% APR");
ExitButton.setFont(new java.awt.Font("Times New Roman", 1, 18)); // NOI18N
ExitButton.setText("Exit");
ExitButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
ExitButtonActionPerformed(evt);
}
});
buttonGroup1.add(year30rate575);
year30rate575.setText("30 years at 5.75% APR");
CalcHead.setFont(new java.awt.Font("Times New Roman", 1, 18)); // NOI18N
CalcHead.setText("McBride Financial Mortgage Calculator");
MonthlyPmtLabel.setFont(new java.awt.Font("Times New Roman", 1, 18)); // NOI18N
MonthlyPmtLabel.setText("Monthly Payment:");
CalcButton.setFont(new java.awt.Font("Times New Roman", 1, 18)); // NOI18N
CalcButton.setText("Calculate");
CalcButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
CalcButtonActionPerformed(evt);
}
});
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jSeparator1, javax.swing.GroupLayout.Alignment.TRAILING)
.addGroup(layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addComponent(MonthlyPmtLabel))
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
.addGroup(layout.createSequentialGroup()
.addGap(45, 45, 45)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(year30rate575)
.addComponent(year15rate550)
.addComponent(year7rate535))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(CalcButton))
.addGroup(layout.createSequentialGroup()
.addGap(229, 229, 229)
.addComponent(CalcHead, javax.swing.GroupLayout.PREFERRED_SIZE, 323, javax.swing.GroupLayout.PREFERRED_SIZE)))
.addGroup(layout.createSequentialGroup()
.addGap(461, 461, 461)
.addComponent(OutputMonthlyPayment, javax.swing.GroupLayout.PREFERRED_SIZE, 133, javax.swing.GroupLayout.PREFERRED_SIZE))
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addGap(476, 476, 476)
.addComponent(ExitButton)
.addGap(18, 18, 18)
.addComponent(ResetButton)
.addGap(9, 9, 9)))
.addGap(0, 198, Short.MAX_VALUE)))
.addContainerGap())
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addComponent(PrincipleLabel)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 463, Short.MAX_VALUE)
.addComponent(jLabel1)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(InputPrincipleAmt, javax.swing.GroupLayout.PREFERRED_SIZE, 181, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(37, 37, 37)))
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addComponent(CalcHead, javax.swing.GroupLayout.PREFERRED_SIZE, 41, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addGap(110, 110, 110)
.addComponent(year7rate535)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(year15rate550)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(year30rate575)
.addGap(35, 35, 35))
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(CalcButton)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)))
.addComponent(jSeparator1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(MonthlyPmtLabel)
.addComponent(OutputMonthlyPayment, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addGap(18, 18, 18)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(ResetButton)
.addComponent(ExitButton))
.addContainerGap(422, Short.MAX_VALUE))
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addGap(96, 96, 96)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(PrincipleLabel)
.addComponent(InputPrincipleAmt, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(jLabel1))
.addContainerGap(691, Short.MAX_VALUE)))
);
pack();
}// </editor-fold>
// End generated code
private void ResetButtonActionPerformed(java.awt.event.ActionEvent evt) {
// This will allow the user to reset the values entered in the text fields
//Each text field should be set to a blank value
InputPrincipleAmt.setText("");
OutputMonthlyPayment.setText("");
//This radio button is set to true which makes the program select it as-
// default when it starts and when the reset button is selected
year7rate535.setSelected(false);
}
private void InputPrincipleAmtValidateAmt(java.awt.event.FocusEvent evt) {
//The following code will validate if the entry from the user is a -
// number and that it meets the requirements to be calculated in the formula
try
{
//This states the InputPrincipleAmt has to be in double format
Double.parseDouble(InputPrincipleAmt.getText());
}
//If the user inputs something in the incorrect format, this message -
// will pop up in a seperate window
catch (Exception e)
{
JOptionPane.showMessageDialog(null,"You must enter a number without commas for the principle amount.");
InputPrincipleAmt.setText("");
OutputMonthlyPayment.setText("");
}
}
private void ExitButtonActionPerformed(java.awt.event.ActionEvent evt) {
// This will allow the user to exit the calculator
System.exit(0);
}
private void CalcButtonActionPerformed(java.awt.event.ActionEvent evt) {
//The variables involved with the calculation button must be entered-
// here and defined.
double MonthlyInterestRate ;
double TermMonths ;
double FormulaNumerator ;
double FormulaDenominator ;
double MonthlyPayment ;
double AnnualRate = 0;
double PrincipleAmt = 0;
int TermYears = 0;
//Arrays
int [] TermYear =
{
7,
15,
30
};
double [] Rate =
{
5.35,
5.50,
5.75
};
boolean okToCalculate = true;
//This allows the program to transform the "text" entered into -
// numbers the formula can calculate
try
{
PrincipleAmt = Double.parseDouble(InputPrincipleAmt.getText());
}
catch (Exception e)
{
JOptionPane.showMessageDialog(null,"You must enter a number without "
+ "commas for the principle amount.");
okToCalculate = false;
InputPrincipleAmt.setText("");
OutputMonthlyPayment.setText("");
}
if (year7rate535.getSelectedObjects() != null)
{
AnnualRate = Rate [0];
TermYears = TermYear [0];
}
else
if (year15rate550.getSelectedObjects() != null)
{
AnnualRate = Rate [1];
TermYears = TermYear [1];
}
else
if (year30rate575.getSelectedObjects() != null)
{
AnnualRate = Rate [2];
TermYears = TermYear[2];
}
if (okToCalculate)
{
//This transforms the number into a currency format
NumberFormat currency = NumberFormat.getCurrencyInstance();
//calculate term months and monthly interest then
// Divide the %interest rate by 100 to return a decimal value
// Divide the results by 12 to return the monthly interest rate
MonthlyInterestRate = (AnnualRate / 100) / 12;
// Multiply the number of years by 12 to return the term in months
TermMonths = TermYears * 12;
//formula numerator and denominator
// Multiply the monthly interest rate by the principle
FormulaNumerator = (MonthlyInterestRate * PrincipleAmt);
// Resolve the forumula M=P[i(1+i)to the power n]/[(1+i)to the power of n -1]
// Use math library, powers function
FormulaDenominator = 1 - (java.lang.Math.pow((1 + MonthlyInterestRate), (-1 * TermMonths)));
// calculate payment amount
MonthlyPayment = FormulaNumerator / FormulaDenominator;
// Display the monthly mortgage payment amount in currency format
OutputMonthlyPayment.setText(currency.format(MonthlyPayment));
}
}
/**
* @param args the command line arguments
*/
public static void main(String args[]) {
/*
* Set the Nimbus look and feel
*/
//<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
/*
* If Nimbus (introduced in Java SE 6) is not available, stay with the
* default look and feel. For details see
* http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html
*/
try {
for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
if ("Nimbus".equals(info.getName())) {
javax.swing.UIManager.setLookAndFeel(info.getClassName());
break;
}
}
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | javax.swing.UnsupportedLookAndFeelException ex) {
java.util.logging.Logger.getLogger(JoeyWeek3b.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
}
//</editor-fold>
/*
* Create and display the form
*/
java.awt.EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
new JoeyWeek3b().setVisible(true);
}
});
}
// Variables declaration - do not modify
private javax.swing.JButton CalcButton;
private javax.swing.JLabel CalcHead;
private javax.swing.JButton ExitButton;
private javax.swing.JTextField InputPrincipleAmt;
private javax.swing.JLabel MonthlyPmtLabel;
private javax.swing.JTextField OutputMonthlyPayment;
private javax.swing.JLabel PrincipleLabel;
private javax.swing.JButton ResetButton;
private javax.swing.ButtonGroup buttonGroup1;
private javax.swing.JLabel jLabel1;
private javax.swing.JSeparator jSeparator1;
private javax.swing.JRadioButton year15rate550;
private javax.swing.JRadioButton year30rate575;
private javax.swing.JRadioButton year7rate535;
// End of variables declaration
}