jab8288 0 Newbie Poster

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
}