java - 仅在按下 JButton 时绘画

标签 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. 仅当 balance2 不为 null 且不为空 (length > 0) 时才绘制图表
  2. 考虑使用 paintComponent 而不是 paint,请参阅 Performing Custom Painting了解更多详情。
  3. 还可以调用 super.paint(如果您已覆盖 paintComponent,则调用 super.paintComponent)来保留绘制链。请参阅Painting in AWT and Swing了解更多详细信息(注意:您正在从 paint 中调用 super.paintComponent,这是个坏主意,可能会影响 GUI 的更新)
  4. 将图表绘制到单独的专用组件上,否则您将在其他组件下面进行绘制
  5. 当您想要重新绘制栏组件的内容时,调用栏组件上的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);
        }
    }
}

关于java - 仅在按下 JButton 时绘画,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27219465/

相关文章:

java - 意外地将字符串添加到 List<Integers>

java - SocketChannel : java. io.IOException: 现有连接被远程主机强行关闭

java - JFileChooser 不遵循外观

python - wxWindows/wxPython 中没有标题栏的窗口

Java 出现错误 'Unhandled exception type XYZ'

java - Primefaces 3.0 : TreeNode and ContextMenu

java - 为什么 requestFocusInWindow() 会失败?

Java - 如何在粘贴操作上设置启用()?

java - 当图像路径更改时,JPanel 中的图像未更新

安卓用户界面 : Multiple Horizontally Paged Table