0

EDIT: My problem seems to lie within the constructor of the AutoInfoLoan class. It's instantiated within the CombinedPanels class as soon as the program is started, so all variables within the class are given default values (some of which are 0). I'm working on figuring this out, but any help is still appreciated.

I'm making an Auto Loan Calculator GUI in Java.

I have all the GUI completed; however, my problem is getting the calculation portion to work.

Before

is the GUI when first launched,

During

is my GUI after entering some values in the "Financing Information" section and changing some other options and clicking "Calculate", and

What if should look like

is what it's supposed to look like after entering those values.

Here are my JPanel subclasses (all of them besides the top banner; that's irrelevant to any calculation):

**Wall of Code Warning

Payment Information:

import java.awt.GridLayout;
import javax.swing.BorderFactory;
import javax.swing.JLabel;
import javax.swing.JPanel;

@SuppressWarnings("serial")
public class PaymentInformation extends JPanel{
//Declare variables
private JPanel payInfo;
private JLabel loanAmt, monthPay, totalPay, loanVal, monthVal, totalVal;

public PaymentInformation(){
    //Give panel layout
    payInfo = new JPanel(new GridLayout(3, 2));
    //Give titles, set alignment
    loanAmt = new JLabel("Total Loan Amount:  $", JLabel.LEFT);
    monthPay = new JLabel("Monthly Payment:  $", JLabel.LEFT);
    totalPay = new JLabel("Total Payment:  $", JLabel.LEFT);
    loanVal = new JLabel("0.0", JLabel.RIGHT);
    monthVal = new JLabel("0.0", JLabel.RIGHT);
    totalVal = new JLabel("0.0", JLabel.RIGHT);
    //Add stuff to JPanel
    payInfo.add(loanAmt);
    payInfo.add(loanVal);
    payInfo.add(monthPay);
    payInfo.add(monthVal);
    payInfo.add(totalPay);
    payInfo.add(totalVal);
    //Set border
    payInfo.setBorder(BorderFactory.createTitledBorder("Payment Information"));
}
//Method to get the JPanel
public JPanel getGUI(){
    return payInfo;
}
//Reset to defaults
public void setDefault(){
    loanVal.setText("0.0");
    monthVal.setText("0.0");
    totalVal.setText("0.0");
}
//Three methods to change the values of the JLabels based on argument received
public void changeLoan(String val){
    loanVal.setText(val);    
}
public void changeMonth(String val){
    monthVal.setText(val);   
}
public void changeTotal(String val){
    totalVal.setText(val);   
}


}

import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.BorderFactory;
import javax.swing.ButtonGroup;
import javax.swing.JPanel;
import javax.swing.JRadioButton;

Loan Term:

@SuppressWarnings("serial")
public class LoanTerm extends JPanel{
private JRadioButton twoFour, threeSix, fourEight, sixZero;
private ButtonGroup loanButtons;
private JPanel lt;
private double ir;
private int loanTerm;
public LoanTerm(){
    //Declare buttons, set 24 month as default
    twoFour = new JRadioButton("24 Months", true);
    threeSix = new JRadioButton("36 Months");
    fourEight = new JRadioButton("48 Months");
    sixZero = new JRadioButton("60 Months");

    //Add all to ButtonGroup
    loanButtons = new ButtonGroup();
    loanButtons.add(twoFour);
    loanButtons.add(threeSix);
    loanButtons.add(fourEight);
    loanButtons.add(sixZero);

    //Create GridLayout within JPanel
    lt = new JPanel(new GridLayout(4,1));
    lt.add(twoFour);
    lt.add(threeSix);
    lt.add(fourEight);
    lt.add(sixZero);

    //Create ActionListeners for buttons
    twoFour.addActionListener(new TermListener());

    //Border
    lt.setBorder(BorderFactory.createTitledBorder("Loan Term"));
    ir = 0;
}


//Method to return JPanel
public JPanel getGUI(){
    return lt;
}
//Method to reset to default selection
public void setDefault(){
    twoFour.setSelected(true);
}

//Next four methods change the interest rate AND loan term integer based on the radio button selection
public void setInterest24(){
    ir = 4.5;
    loanTerm = 24;
}
public void setInterest36(){
    ir = 5.5;
    loanTerm = 36;
}
public void setInterest48(){
    ir = 6.5;
    loanTerm = 48;
}
public void setInterest60(){
    ir = 7.0;
    loanTerm = 60;
}
//Return the interest rate
public double returnInterest(){
    return ir;
}
//Return loan term
public int returnLoanTerm(){
    return loanTerm;
}

private class TermListener implements ActionListener{
    //TODO change interest rate based on selection
    //If a certain button is pressed, interest rate is changed based on selection
    @Override
    public void actionPerformed(ActionEvent e) {
        if(twoFour.isSelected()){
            setInterest24();
        }
        if(threeSix.isSelected()){
            setInterest36();
        }
        if(fourEight.isSelected()){
            setInterest48();
        }
        if(sixZero.isSelected()){
            setInterest60();
        }

    }

}

}

Price with Options:

import java.awt.GridLayout;

import javax.swing.BorderFactory;
import javax.swing.JCheckBox;
import javax.swing.JPanel;


@SuppressWarnings("serial")
public class PriceWithOptions extends JPanel{
private JPanel pwo;
private JCheckBox trans, brake, sun, nav, audio;
private double total;
public PriceWithOptions(){
    //Set GridLayout within JPanel
    pwo = new JPanel(new GridLayout(5, 1));

    //Declare JCheckBoxes (make AntiLock Brakes default checked)
    trans = new JCheckBox("Auto Transmission: $1,800");
    brake = new JCheckBox("Anti-Lock Brakes: $1,200", true);
    sun = new JCheckBox("Sun Roof: $800");
    nav = new JCheckBox("Navigation System: $1,350");
    audio = new JCheckBox("Audio Package: $1,550");

    //Add CheckBoxes to the JPanel
    pwo.add(trans);
    pwo.add(brake);
    pwo.add(sun);
    pwo.add(nav);
    pwo.add(audio);

    //Add border
    pwo.setBorder(BorderFactory.createTitledBorder("Price with Options"));
}

//Method to return JPanel
public JPanel getGUI(){
    return pwo;
}
//Set defaults
public void setDefault(){
    trans.setSelected(false);
    brake.setSelected(true);
    sun.setSelected(false);
    nav.setSelected(false);
    audio.setSelected(false);
}
//Method to calculate the total costs of selected options
public double calculateCost(){
    total = 0;
    if(trans.isSelected()){
        total += 1800;
    }
    if(brake.isSelected()){
        total += 1200;
    }
    if(sun.isSelected()){
        total += 800;
    }
    if(nav.isSelected()){
        total += 1350;
    }
    if(audio.isSelected()){
        total += 1550;
    }
    return total;
}
}

Financing Information:

import java.awt.GridLayout;
import javax.swing.BorderFactory;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;


public class FinancingInformation {
private JLabel base, down, tax;
private JTextField baseTxt, downTxt, taxTxt;
private JPanel fi;
public FinancingInformation(){
    //Declare panel layout
    fi = new JPanel(new GridLayout(3, 2));

    //Declare JLabels
    base = new JLabel("Base Price:  $ ", JLabel.LEFT);
    down = new JLabel("Down Payment:  $ ", JLabel.LEFT);
    tax = new JLabel("Sales Tax:  % ", JLabel.LEFT);

    //Declare JTextFields
    baseTxt = new JTextField("0.0", 15);
    downTxt = new JTextField("0.0", 15);
    taxTxt = new JTextField("7.0", 15);

    //Put it all in JPanel
    fi.add(base);
    fi.add(baseTxt);
    fi.add(down);
    fi.add(downTxt);
    fi.add(tax);
    fi.add(taxTxt);

    //Set border
    fi.setBorder(BorderFactory.createTitledBorder("Financing Information"));
}

//Method to return JPanel
public JPanel getGUI(){
    return fi;
}
//Set Defaults
public void setDefault(){
    baseTxt.setText("0.0");
    downTxt.setText("0.0");
    taxTxt.setText("7.0");
}

//Following methods all convert JLabels into doubles, then return the value
public double returnBaseVal(){
    String baseString = baseTxt.getText();
    double base = Double.parseDouble(baseString);
    return base;
}

public double returnDownVal(){
    String downString = downTxt.getText();
    double down = Double.parseDouble(downString);
    return down;
}

public double returnTaxVal(){
    String taxString = taxTxt.getText();
    double tax = Double.parseDouble(taxString);
    tax = tax/100;
    return tax;
}
}

A class to do all the calculations (AutoInfoLoan):

import java.text.DecimalFormat;


public class AutoInfoLoan {
private double totalLoanAmount, monthlyPayment, totalPayment, basePrice, optionCost, downPayment, salesTax, salesTaxAmount, interestRate;
private int loanTerm;
PaymentInformation pi;
FinancingInformation fi;
PriceWithOptions pwo;
LoanTerm lt;
DecimalFormat df = new DecimalFormat("#.00");

public AutoInfoLoan(PaymentInformation pi, LoanTerm lt, FinancingInformation fi, PriceWithOptions pwo){
    this.pi = pi;
    this.lt = lt;
    this.fi = fi;
    this.pwo = pwo;
    basePrice = this.fi.returnBaseVal();
    downPayment = this.fi.returnDownVal();
    salesTax = this.fi.returnTaxVal();
    interestRate = this.lt.returnInterest();
    loanTerm = this.lt.returnLoanTerm();
    optionCost = this.pwo.calculateCost();
}

//Method to set the salesTaxAmount
public void setSalesTax(){
    salesTaxAmount = (basePrice - downPayment + optionCost) * salesTax;
}
//Method to set total loan amount
public void setTotalLoanAmount(){
    totalLoanAmount = basePrice - downPayment + optionCost + salesTaxAmount;
}
//Method to set the monthly payment
public void setMonthlyPayment(){
    double rate = interestRate / 12;
    monthlyPayment = totalLoanAmount * rate / (1 - (Math.pow(1/(1+rate), loanTerm)));
}
//Method to set total payment
public void setTotalPayment(){
    totalPayment = monthlyPayment * loanTerm + downPayment;
}

//Three methods that call change methods within the PaymentInformation class to change the JLabel values
public void returnTotalLoanAmount(){
    pi.changeLoan(df.format(totalLoanAmount));
}

public void returnMonthlyPayment(){
    pi.changeMonth(df.format(monthlyPayment));
}

public void returnTotalPayment(){
    pi.changeTotal(df.format(totalPayment));
}

//Method to execute everything, called upon in the ActionButton listener

public void executeClass(){
    setSalesTax();
    setTotalLoanAmount();
    setMonthlyPayment();
    setTotalPayment();
    returnTotalLoanAmount();
    returnMonthlyPayment();
    returnTotalPayment();
}
}

And, finally, a class to put all JPanels together into a JFrame and make an instance of the calculation class:

import java.awt.BorderLayout;
import java.awt.GridLayout;
import javax.swing.JFrame;
import javax.swing.JPanel;


@SuppressWarnings("serial")
public class CombinedPanels extends JFrame{
public CombinedPanels(){
    setTitle("Auto Loan Calculator");
    setSize(700,500);
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    setLayout(new BorderLayout());
    JPanel center = new JPanel(new GridLayout(2, 2, 20, 20));

    //Add other classes to this layout
    TitleBar tb = new TitleBar();
    PaymentInformation pi = new PaymentInformation();
    LoanTerm lt = new LoanTerm();
    FinancingInformation fi = new FinancingInformation();
    PriceWithOptions pwo = new PriceWithOptions();
    AutoInfoLoan ail = new AutoInfoLoan(pi, lt, fi, pwo);
    ActionButtons ab = new ActionButtons(pi, lt, fi, pwo, ail);

    //Add JPanels
    add(tb.getGUI(), BorderLayout.NORTH);
    add(ab.getGUI(), BorderLayout.SOUTH);

    //Add center JPanel to the center of BorderLayout
    add(center, BorderLayout.CENTER);

    //Continue with adding rest of classes to center JPanel
    center.add(pi.getGUI());
    center.add(lt.getGUI());
    center.add(fi.getGUI());
    center.add(pwo.getGUI());
}
}

I believe the start of my problem lies somewhere with the "Price with Options" section. The default selection in that JPanel is the Antilock Brakes, which cost 1200. The "Total Loan Amount" JLabel within the Payment Information class always seems to calculate out to 1200 + 7% sales tax (also a default value for that JTextField) regardless of what information is entered or selected. I've been trying for hours with no luck, so any insight on this problem is much appreciated.

  • Have a look at [Model-View-Controller](http://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller). Essentially, you need some kind of model which models your data and provides information to one or more of your views. The model may also provide notification of when changes are made, allow other parts of the UI to update their state accordingly – MadProgrammer Sep 28 '15 at 00:02
  • You should read this first : http://stackoverflow.com/help/mcve – Yassin Hajaj Sep 28 '15 at 00:02

2 Answers2

0

The reason because you've been looking to it for hours with no luck is because the bussiness logic of the application is mixed up with the GUI. It is difficult to follow the flow of the calculations, since they are modelled after how the GUI works, instead of how a loan should be calculated.

Take a look at the first answer to this question. I think it will give you the answer on how to organize your code. Once you have a good design implemented, the source of the bug will be probably obvious.

Community
  • 1
  • 1
Baltasarq
  • 12,014
  • 3
  • 38
  • 57
  • My Model is the AutoInfoLoan class, the multiple panels are the view, and the CombinedPanels as well as the class that instantiates it (LoanCalculateGUI, not shown here as it's only 2 lines long) are the controller. I thought I already had somewhat of a MVC design implemented. – David Meredith Sep 28 '15 at 00:52
  • Okay, think about it this way: could you change the user interface for a text one, without modifying the logic, i.e., how the loan is calculated? – Baltasarq Sep 28 '15 at 09:14
0

I figured out what I was doing wrong. First, only one of the JRadioButtons had an ActionListener on it (stupid me). Also, the values in the AutoInfoLoan class (the calculation class) were all set to the default values as soon as the program launched. I had to add some extra setter methods within that class to actually get the correct numbers. Hopefully this might help someone else so they don't repeat my silly mistakes.