私のプロジェクトでは、カスタム形状のボタンを作成したいと考えています。私は円形のボタンを作成するためのコードを持っています。多くの調査の結果、透過性のある 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);
}
}
それで、コードのどこが間違っていたのか、誰でも教えてもらえますか?また、生成された形状をある種のファイルに保存して、プログラムの実行中に常に形状を再生成する必要がないようにする方法はありますか? または、形状を事前にキャッシュする方法はありますか。