0

对于我的项目,我想创建自定义形状的按钮。我有创建圆形按钮的代码,经过大量研究,我设法找到了一些代码,可用于从具有透明度的 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)

这是我的自定义按钮类:

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

那么,任何人都可以指导我代码哪里出错了?有没有什么办法可以将生成的形状保存到某种文件中,以便在程序运行时不必总是重新生成形状?或者有什么方法可以预先缓存形状。

4

1 回答 1

0

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

于 2012-05-30T09:06:18.413 回答