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

Java-从PNG图像创建形状(NullPointerException),java,nullpointerexception,draw,shape,area,Java,Nullpointerexception,Draw,Shape,Area,对于我的项目,我想创建自定义形状的按钮。我已经有了创建圆形按钮的代码,经过大量研究,我找到了一些代码,可以用来从一个透明的PNG图像生成一个形状(区域),这样我就可以使用这些代码并将其放入我的自定义按钮程序中。但是,创建形状的过程需要cpu,并且创建每个形状需要相当长的时间。以下是我从图像生成形状的代码: import java.awt.Rectangle; import java.awt.geom.Area; import java.awt.image.BufferedImage; publ

对于我的项目,我想创建自定义形状的按钮。我已经有了创建圆形按钮的代码,经过大量研究,我找到了一些代码,可以用来从一个透明的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;
    }
}
这是我的自定义按钮类:

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

那么,有人能告诉我代码哪里出了问题吗?有没有办法将生成的形状保存到某种文件中,这样在程序运行时就不必总是重新生成形状?或者是否有任何方法来预切形状。

您没有检查
图像
参数是否为
。查看您的调用方法
initShape
如果无法读取“Untitled1.png”,您可以得到一个空指针。

谢谢,它解决了问题:感谢您,通过添加检查图像是否为空,解决了问题。
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);
    }
}