I have a class extending JButton
that I am trying to apply a .png image to.
The image is irregular in shape, and is surrounded by transparent pixels. I have overridden the paintComponent()
method in the JButton
to apply my buffered image to the button. Right now, the image is the only thing being drawn, which is what I want.
However, the button is still detecting events in the rectangle around it. Is there a way to limit detection to only the area containing opaque pixels (or rather to not detect events on the transparent pixels)?
Code for button class is below.
public class DrawButton extends JButton{
private BufferedImage bi;
public DrawButton(BufferedImage bi){
setPreferredSize(new Dimension(bi.getWidth(), bi.getHeight()));
this.bi = bi;
}
@Override
protected void paintComponent(Graphics g){
g.drawImage(bi, 0, 0, null);
g.dispose();
}
}
Well I would suggest using a MouseAdapter
, and override mouseClicked(..)
. In mouseClicked
check if pixel is alpha at point of click if it is do nothing, if not do something.
super.paintComponent(..)
as first call in overriden paintComponent
method, but because, especially with buttons, this will redraw the JButton
background call setContentAreaFilled(false)
on JButton
instance to stop this. You may also want setBorderPainted(false)
too.Here is a small example I made (adapted from here):
if click on smiley:
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.RenderingHints;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.net.URL;
import javax.imageio.ImageIO;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.SwingUtilities;
public class TransparentButton {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
final JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
MyButton button = null;
try {
button = new MyButton(scaleImage(100, 100, ImageIO.read(new URL("http://2.bp.blogspot.com/-eRryNji1gQU/UCIPw0tY5bI/AAAAAAAASt0/qAvERbom5N4/s1600/original_smiley_face.png"))));
} catch (Exception ex) {
ex.printStackTrace();
}
button.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent me) {
super.mouseClicked(me);
MyButton mb = ((MyButton) me.getSource());
if (!isAlpha(mb.getIconImage(), me.getX(), me.getY())) {
JOptionPane.showMessageDialog(frame, "You clicked the smiley");
}
}
private boolean isAlpha(BufferedImage bufImg, int posX, int posY) {
int alpha = (bufImg.getRGB(posX, posY) >> 24) & 0xFF;
return alpha == 0;
}
});
frame.add(button);
frame.pack();
frame.setVisible(true);
}
});
}
public static BufferedImage scaleImage(int w, int h, Image img) throws Exception {
BufferedImage bi;
bi = new BufferedImage(w, h, BufferedImage.TRANSLUCENT);
Graphics2D g2d = (Graphics2D) bi.createGraphics();
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.addRenderingHints(new RenderingHints(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY));
g2d.drawImage(img, 0, 0, w, h, null);
return bi;
}
}
class MyButton extends JButton {
BufferedImage icon;
MyButton(BufferedImage bi) {
this.icon = ((BufferedImage) bi);
setContentAreaFilled(false);
}
@Override
public Dimension getPreferredSize() {
return new Dimension(icon.getWidth(), icon.getHeight());
}
public BufferedImage getIconImage() {
return icon;
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(icon, 0, 0, this);
}
}