简体   繁体   English

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

[英]Java - Create Shape From PNG Image (NullPointerException)

for my project, i want to create custom shaped buttons. 对于我的项目,我想创建自定义形状的按钮。 i've got the codes to create circular buttons, and after much research, i managed to find some codes that i can use to generate a shape(area) from a PNG image with transparency, so that i can use the code and put it into my custom button program. 我已经有了创建圆形按钮的代码,经过大量研究,我设法找到了一些代码,可以用来从具有透明性的PNG图像生成形状(区域),以便我可以使用代码并将其放入进入我的自定义按钮程序。 however, the process of creating the shape is cpu-consuming, and it takes quite a long time for creating each shape. 但是,创建形状的过程非常消耗CPU,并且创建每个形状都需要花费很长时间。 Here is my code for generating a shape from an image: 这是我的用于从图像生成形状的代码:

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

by using the code above, there will be a NullPointerException error. 通过使用上面的代码,将出现NullPointerException错误。 here's the stacktrace: 这是堆栈跟踪:

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)

here is my CustomButtonClass: 这是我的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);
    }
}

so, can anyone guide me on where did i go wrong with the code? 因此,有人可以指导我我在哪里弄错了代码吗? and is there any way that the shape generated can be saved into some sort of files so that it does not have to always regenerate the shape whenever the program is being run? 并且有什么方法可以将生成的形状保存到某种文件中,以便在运行程序时不必总是重新生成形状? or is there any way to precache the shape. 或有什么方法可以预缓存形状。

You have no check if the image parameter is null . 您无需检查image参数是否为null Looking at your calling method initShape you can get a null pointer if the "Untitled1.png" cannot be read. 查看调用方法initShape ,如果无法读取“ Untitled1.png”,则可以得到一个空指针。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM