2012-05-30 111 views
0

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

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

因此,任何人都可以指导我在哪里,我去错误的代码?并且有什么方法可以将生成的形状保存到某种文件中,以便在程序运行时不必总是重新生成形状?或者有什么办法来预备形状。

+0

检查'image'是否为空。 –

+0

感谢它解决了这个问题:D – csharpnewbie

回答

1

如果image参数为null,则不检查。看看你的调用方法initShape如果无法读取“Untitled1.png”,你可以得到一个空指针。

+0

谢谢,通过添加一个检查图像是否为空,解决了这个问题。 – csharpnewbie