Java - 从PNG图像创建形状(NullPointerException)

时间:2012-05-30 09:03:06

标签: java nullpointerexception draw shape area

对于我的项目,我想创建自定义形状的按钮。我已经有了创建圆形按钮的代码,经过大量的研究,我设法找到一些代码,我可以使用它来生成具有透明度的PNG图像的形状(区域),这样我就可以使用代码并将其放入进入我的自定义按钮程序。但是,创建形状的过程是消耗cpu的,并且创建每个形状需要相当长的时间。这是我从图像生成形状的代码:

import java.awt.Rectangle;
import java.awt.geom.Area;
import java.awt.image.BufferedImage;

public class CreateShapeClass {
    public static Area createArea(BufferedImage image, int maxTransparency) {
        Area area = new Area();
        Rectangle rectangle = new Rectangle();
        for (int x = 0; x < image.getWidth(); x++) {
            for (int y = 0; y < image.getHeight(); y++) {
                int rgb = image.getRGB(x, y);
                rgb = rgb >>> 24;
                if (rgb >= maxTransparency) {
                    rectangle.setBounds(x, y, 1, 1);
                    area.add(new Area(rectangle));
                }
            }
        }
        return area;
    }
}

使用上面的代码,会出现NullPointerException错误。这是堆栈跟踪:

java.lang.NullPointerException
at CreateShapeClass.createArea(CreateShapeClass.java:10)
at CustomButton.initShape(CustomButton.java:95)
at CustomButton.paintBorder(CustomButton.java:102)
at javax.swing.JComponent.printBorder(Unknown Source)
at javax.swing.JComponent.paint(Unknown Source)
at javax.swing.JComponent.print(Unknown Source)
at javax.swing.JComponent.paintChildren(Unknown Source)
at javax.swing.JComponent.printChildren(Unknown Source)
at javax.swing.JComponent.paint(Unknown Source)
at javax.swing.JComponent.print(Unknown Source)
at javax.swing.JComponent.paintChildren(Unknown Source)
at javax.swing.JComponent.printChildren(Unknown Source)
at javax.swing.JComponent.paint(Unknown Source)
at javax.swing.JLayeredPane.paint(Unknown Source)
at javax.swing.JComponent.print(Unknown Source)
at javax.swing.JComponent.paintChildren(Unknown Source)
at javax.swing.JComponent.printChildren(Unknown Source)
at javax.swing.JComponent.paint(Unknown Source)
at javax.swing.JComponent.print(Unknown Source)
at java.awt.GraphicsCallback$PrintCallback.run(Unknown Source)
at sun.awt.SunGraphicsCallback.runOneComponent(Unknown Source)
at sun.awt.SunGraphicsCallback.runComponents(Unknown Source)

这是我的CustomButtonClass:

import java.awt.*;
import java.awt.geom.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.util.Iterator;

import javax.imageio.ImageIO;
import javax.imageio.ImageReadParam;
import javax.imageio.ImageReader;
import javax.imageio.stream.ImageInputStream;
import javax.swing.*;

public class CustomButton extends JButton {
    protected Shape shape, base;
    protected BufferedImage image;
    protected String imagePath;

    private static final long serialVersionUID = 1L;
    public CustomButton() {
        this(null, null);
    }
    //takes in an icon
    public CustomButton(Icon icon) {
        this(null, icon);
    }
    //takes in a text string for button
    public CustomButton(String text) {
        this(text, null);
    }

    //takes in a text string for button
    public CustomButton(Icon icon, String imagePath, boolean useless) {
        this(null, icon);
        this.imagePath = imagePath;
    }
    //takes in an action for the button press event
    public CustomButton(Action a) {
        this();
        setAction(a);
    }
    //takes in text and icon image
    public CustomButton(String text, Icon icon) {
        setModel(new DefaultButtonModel());
        init(text, icon);
        if(icon==null) {
            return;
        }
        setBorder(BorderFactory.createEmptyBorder(0,0,0,0));
        setBackground(Color.BLACK);
        setContentAreaFilled(false);
        setFocusPainted(false);
        //setVerticalAlignment(SwingConstants.TOP);
        setAlignmentY(Component.TOP_ALIGNMENT);
        initShape();
    }

    //creates a method for retrieving preferred size of the button (the image)
    @Override public Dimension getPreferredSize() {
        Icon icon = getIcon();
        Insets i = getInsets();
        if (icon == null){
            return super.getPreferredSize();
        }
        else {
            return new Dimension(icon.getIconWidth(), icon.getIconHeight());
        }
    }

    //creates the shape of the button from the image
    protected void initShape() {
        if(!getBounds().equals(base)) {
            Dimension s = getPreferredSize();
            base = getBounds();
            if (image == null){
                try {
                    image = ImageIO.read(new File("Untitled1.png"));
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            shape = CreateShapeClass.createArea(image, 25);
            System.out.println(shape.getBounds());
        }
    }

    //creates the border of the button
    @Override protected void paintBorder(Graphics g) {
        initShape();
        Graphics2D g2 = (Graphics2D)g;
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        g2.setColor(getBackground());
        g2.setStroke(new BasicStroke(1.0f));
        g2.draw(shape);
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF);
    }
    @Override public boolean contains(int x, int y) {
        initShape();
        return shape.contains(x, y);
    }
}

所以,任何人都可以指导我在哪里出错代码?并且有什么方法可以将生成的形状保存到某种文件中,这样一旦程序运行它就不必总是重新生成形状?或者有什么方法可以预先形成。

1 个答案:

答案 0 :(得分:1)

您无法检查image参数是否为null。查看调用方法initShape如果无法读取“Untitled1.png”,则可以获得空指针。