【问题标题】:Changing Values across multiple classes跨多个类更改值
【发布时间】:2015-09-27 23:55:12
【问题描述】:

编辑:我的问题似乎出在 AutoInfoLoan 类的构造函数中。一旦程序启动,它就会在 CombinedPanels 类中实例化,因此类中的所有变量都被赋予默认值(其中一些是 0)。我正在努力解决这个问题,但仍然感谢任何帮助。

我正在用 Java 制作汽车贷款计算器 GUI。

我已经完成了所有的 GUI;但是,我的问题是让计算部分起作用。

是首次启动时的 GUI,

是我在“融资信息”部分输入一些值并更改其他一些选项并单击“计算”后的 GUI,并且

是输入这些值后的样子。

这是我的JPanel 子类(除了顶部横幅之外的所有子类;这与任何计算都无关):

**代码警告墙

付款信息:

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;

贷款期限:

@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();
        }

    }

}

}

选项价格:

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;
}
}

融资信息:

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;
}
}

一个做所有计算的类(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();
}
}

最后,还有一个类将所有 JPanel 组合成一个 JFrame 并创建计算类的实例:

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());
}
}

我相信我的问题的根源在于“带选项的价格”部分。该 JPanel 中的默认选择是 Antilock Brakes,成本为 1200。Payment Information 类中的“总贷款金额”JLabel 似乎总是计算为 1200 + 7% 销售税(也是该 JTextField 的默认值),无论输入或选择了什么信息。我已经尝试了几个小时没有运气,因此非常感谢您对这个问题的任何见解。

【问题讨论】:

  • 看看Model-View-Controller。本质上,您需要某种模型来模拟您的数据并向您的一个或多个视图提供信息。该模型还可以提供有关何时进行更改的通知,允许 UI 的其他部分相应地更新其状态
  • 你应该先阅读这个:stackoverflow.com/help/mcve

标签: java class user-interface jframe jlabel


【解决方案1】:

原因是因为应用程序的业务逻辑与 GUI 混淆了几个小时,但没有成功。很难跟踪计算的流程,因为它们是根据 GUI 的工作方式建模的,而不是应如何计算贷款。

看看this question的第一个答案。我认为它将为您提供有关如何组织代码的答案。一旦你实现了一个好的设计,错误的根源可能会很明显。

【讨论】:

  • 我的模型是 AutoInfoLoan 类,多个面板是视图,CombinedPanels 以及实例化它的类(LoanCalculateGUI,这里没有显示,因为它只有 2 行长)是控制器。我以为我已经实现了某种 MVC 设计。
  • 好吧,这样想:你能不能把用户界面换成文字界面,而不修改逻辑,即贷款是如何计算的?
【解决方案2】:

我发现我做错了什么。首先,只有一个 JRadioButtons 上有一个 ActionListener(我真傻)。此外,AutoInfoLoan 类(计算类)中的值在程序启动后立即全部设置为默认值。我必须在该类中添加一些额外的 setter 方法才能真正获得正确的数字。希望这可能对其他人有所帮助,以免他们重复我的愚蠢错误。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-17
    • 2021-01-13
    • 1970-01-01
    • 2011-09-28
    相关资源
    最近更新 更多