仅在JButton按下绘画

时间:2014-11-30 23:19:39

标签: java swing user-interface jbutton paintcomponent

我是一个java新手,到目前为止我在java中最薄弱的地方是使用图形。我正在尝试制作一个退休计算器,允许用户通过JTextFields将几个数据输入到应用程序中,然后按一个按钮计算每年的帐户余额(即在每个结束时创建一个余额数组)年)。但是,我想使用表示这些余额的条形图来显示此信息,因此条形图必须使用数组中的数字绘制其矩形。但是,由于在程序开始时调用了paintComponent,并且在按下JButton之前没有初始化数组的值,我不能让paintComponent方法引用那些值,否则在运行时会得到nullPointerException。事情没有正确呈现。这是我的代码:

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class Calculator extends JPanel
{

static double start;
static double age;
static double retirement;
static double apr;
static double inflation;
static double daily;
static double life;
static double income;

static int yearsToRetirement = (int)(retirement - age);
static int yearsPostRetirement = (int)(life - retirement);
static double real = (1.0 + (apr / 100.0))/(1.0 + (inflation/100.0)) - 1.0;
static double[] balance;
static double[] yearEndBalance;
static double[] balance2;

public Calculator()
{
    setLayout(new BorderLayout());


    JPanel subpanel = new JPanel();
    add(subpanel, BorderLayout.LINE_END);

    subpanel.setBackground(Color.GRAY);
    subpanel.setLayout(new GridLayout(9, 1));

    // Daily savings
    JPanel pnlDailySavings = new JPanel();
    JLabel lblDailySavings = new JLabel("Daily savings amount:");
    final JTextField txtDailySavings = new JTextField(10);
    pnlDailySavings.add(lblDailySavings);
    pnlDailySavings.add(txtDailySavings);
    subpanel.add(pnlDailySavings);

    // Age
    JPanel pnlAge = new JPanel();
    JLabel lblAge = new JLabel("               Current age:");
    final JTextField txtAge = new JTextField(10);
    pnlAge.add(lblAge);
    pnlAge.add(txtAge);
    subpanel.add(pnlAge);

    // Starting amount of savings
    JPanel pnlStart = new JPanel();
    JLabel lblStart = new JLabel("Starting amount of savings:");
    final JTextField txtStart = new JTextField(10);
    pnlStart.add(lblStart);
    pnlStart.add(txtStart);
    subpanel.add(pnlStart);

    // Age of retirement
    JPanel pnlRetirement = new JPanel();
    JLabel lblRetirement = new JLabel("Expected age of retirement:");
    final JTextField txtRetirement = new JTextField(10);
    pnlRetirement.add(lblRetirement);
    pnlRetirement.add(txtRetirement);
    subpanel.add(pnlRetirement);

    // Annual retirement income
    JPanel pnlIncome = new JPanel();
    JLabel lblIncome = new JLabel("Annual retirement income:");
    final JTextField txtIncome = new JTextField(10);
    pnlIncome.add(lblIncome);
    pnlIncome.add(txtIncome);
    subpanel.add(pnlIncome);

    // Life expectancy
    JPanel pnlLife = new JPanel();
    JLabel lblLife = new JLabel("Life expectancy:");
    final JTextField txtLife = new JTextField(10);
    pnlLife.add(lblLife);
    pnlLife.add(txtLife);
    subpanel.add(pnlLife);

    // Estimated rate of return on savings
    JPanel pnlReturn = new JPanel();
    JLabel lblReturn = new JLabel("Estimated rate of return on savings:");
    final JTextField txtReturn = new JTextField(10);
    pnlReturn.add(lblReturn);
    pnlReturn.add(txtReturn);
    subpanel.add(pnlReturn);

    // Estimated rate of inflation
    JPanel pnlInflation = new JPanel();
    JLabel lblInflation = new JLabel("Estimated rate of inflation:");
    final JTextField txtInflation = new JTextField(10);
    pnlInflation.add(lblInflation);
    pnlInflation.add(txtInflation);
    subpanel.add(pnlInflation);

    JButton btnCalculate = new JButton("Calculate your retirement savings");
    btnCalculate.addActionListener(new ActionListener()
    {
        public void actionPerformed(ActionEvent e)
        {
            daily = Double.parseDouble(txtDailySavings.getText());
            age = Double.parseDouble(txtAge.getText());
            start = Double.parseDouble(txtStart.getText());
            retirement = Double.parseDouble(txtRetirement.getText());
            income = Double.parseDouble(txtIncome.getText());
            life = Double.parseDouble(txtLife.getText());
            apr = Double.parseDouble(txtReturn.getText());
            inflation = Double.parseDouble(txtInflation.getText());
            System.out.printf("%f%n%f%n%f%n%f%n%f%n%f%n%f%n%f%n", daily, age, start, retirement, income, life, apr, inflation);



            balance = new double[365 * yearsToRetirement];
            yearEndBalance = new double[yearsToRetirement];
            balance2 = new double[yearsPostRetirement];


            double total = start;
            for (int i = 0; i < balance.length; i++)
            {
                total = total * (1 + real/365.0) + daily;
                balance[i] = total;
            }

            for (int i = 0; i < balance2.length; i++)
            {
                total = total * Math.pow((1 + real/365.0), 365) - income;
                balance2[i] = total;
            }

            for (int i = 0; i < yearEndBalance.length; i++)
            {
                yearEndBalance[i] = balance[365 * i];
            }

            printArray(yearEndBalance);
            printArray(balance2);

            printArray(balance);

            repaint();

        }
    });
    subpanel.add(btnCalculate);
}

public static void printArray(double[] array)
{
    for (int i = 0; i < array.length; i++)
    {
        System.out.println(array[i]);
    }
}

public void paintComponent(Graphics g)
{
    int width = this.getWidth();
    int height = this.getHeight();
    super.paintComponent(g);
    g.setColor(Color.BLACK);

    g.drawLine((int)(width - 0.9 * width), (int)(height - 0.1 * height), (int)(width - 0.1 * width), (int)(height - 0.1 * height)); 


    for (int i = 0; i <  balance2.length; i++)
    {
        g.fillRect(((int)(width - 0.9 * width) + 5 * i), ((int)(height - 0.1 * height) - 5 * i), 5, 5 * i);
    }
}
} 

这段代码显然是一项正在进行的工作,但是现在我最大的障碍是促进在JButton上创建的数组与创建条形图之间的通信。有人可以帮忙吗?

1 个答案:

答案 0 :(得分:2)

五件事......

  1. 如果balance2不是null且不为空(length&gt; 0
  2. ,则仅绘制图表
  3. 考虑使用paintComponent而不是paint,有关详细信息,请参阅Performing Custom Painting
  4. 如果您已覆盖super.paint,请致电super.paintComponent(或paintComponent)以保留油漆链。有关详细信息,请参阅Painting in AWT and Swing(nb:您正在super.paintComponent内调用paint,这不是一个好主意,可能会影响对GUI的更新)
  5. 将图表绘制为单独的专用组件,否则您将在其他组件下绘画
  6. 如果要重新绘制内容
  7. ,请在条形组件上调用repaint

    例如......

    @Override
    protected void paintComponent(Graphics g)
    {
        super.paintComponent(g);
        int width = this.getWidth();
        int height = this.getHeight();
    
        if (balance2 != null && balance2.length > 0) {
            g.setColor(Color.BLACK);
            g.drawLine((int)(width - 0.9 * width), (int)(height - 0.1 * height), (int)(width - 0.1 * width), (int)(height - 0.1 * height)); 
    
            for (int i = 0; i <  balance2.length; i++)
            {
                g.fillRect(((int)(width - 0.9 * width) + 5 * i), ((int)(height - 0.1 * height) - 5 * i), 5, 5 * i);
            }
        }
    }