Christian Silva
Christian Silva

Reputation: 37

Painting ONLY upon JButton press

I'm a java novice, and by far my weakest point in java is using graphics. I'm trying to make a retirement calculator that allows a user to input several pieces of data into an application through JTextFields and then press a button to calculate an account balance at each year (i.e. create an array of the balances at the end of each year). However, I want to display this information using a bar graph representing these balances, so the bar graph must draw its rectangles using the numbers in the array. However, since paintComponent is called at the beginning of the program and the values of the array aren't initialized until the press of the JButton, I can't have the paintComponent method refer to those values, otherwise I get a nullPointerException upon running and things don't render properly. Here's my code:

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

This code is obviously a work in progress, but right now my biggest hurdle is facilitating the communication between the arrays created upon JButton and creation of a bar graph. Can anyone help?

Upvotes: 0

Views: 57

Answers (1)

MadProgrammer
MadProgrammer

Reputation: 347184

Five things...

  1. Only paint the graph if the balance2 is not null and is not empty (length > 0)
  2. Consider using paintComponent over paint, see Performing Custom Painting for more details.
  3. Also call super.paint (or super.paintComponent if you've overridden paintComponent) to preserve the paint chain. See Painting in AWT and Swing for more details (nb: You are calling super.paintComponent from within paint, this is bad idea and could affect updates to the GUI)
  4. Paint your graph to a separate, dedicated component, otherwise you will be painting underneath the other components
  5. Call repaint on the bar component when you want to repaint it's content

For example..

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

Upvotes: 2

Related Questions