Skip to main content

ImageIcon mouse clicks?

5 replies [Last post]
Joined: 2008-06-08

I have an array of 11 x 11 "Pieces" that hold an ImageIcon of a hexagon. I drew the hexagons onto a JPanel using the paintIcon(this, g, row, col) method.

Now I am trying to see which Piece is clicked using a MouseListener, but when I added the MouseListener to the Panel, it would be unable to see any of the Icons. When I added the MouseListener to the Icon, it wouldn't respond when I clicked anything.

Advice on how to make Icons recognize mouse clicks from within a JPanel?

I can't put the Icon onto a JButton because the hexagons interlock like this:

Quick responses would be appreciated, thanks!

Reply viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
Joined: 2007-05-28

Yes JButtons are rectangular and non-rectangular components are a maybe in java7 I think.
For now, you can still get your effect, but what you have to do is have custom paint and mouse click detection code.

So your program "knows" (can commpute a yes/no decision quickly) what points exist in each hex and when the point of the mouse click hits a particular hex, your program then detects this and repaints that hit hex to look however it's supposed to look when it's pressed on.

So you need a custom mouse listener and you need to override paint in JButton (or perhaps use JLabel since the painting of JButton actually works against you in the sense it's something you need to undo).

The squareness of the button (or label) remains a fact, but it's basically irrelevant, since you *act* as though it wasn't square, where "act as though" == "react to mouse clicks as though and paint as though"


Joined: 2008-06-08

Thanks for the fast response

Doesn't JButton create a square around the hexagon though? Currently I got it to work by creating a Polygon as so:

int w = icon.getIconWidth();
int h = icon.getIconHeight();
xpts[0] = x + w/4;
ypts[0] = y;
//top left

xpts[1] = x + w*3/4;
ypts[1] = y;
//top right

xpts[2] = x + w;
ypts[2] = y+h/2;
//far right

xpts[3] = x+ w*3/4;
ypts[3] = y+h;
//bottom right

xpts[4] = x+ w/4;
ypts[4] = y+h;
//bottom left

xpts[5] = x;
ypts[5] = y+ h/2;
//far left

Polygon borders = new Polygon(xpts, ypts, 6);

however, now my program doesn't update the image inside of the MouseAdapter. any suggestions?

Joined: 2003-07-17


I hacked some code to demonstrate a possible solution:

import java.awt.Color;
import java.awt.Component;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.util.Map;
import java.util.WeakHashMap;

import javax.swing.Icon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.SwingUtilities;

public class TestMouseAwareIcon {

public static class MouseAwareIcon extends MouseAdapter implements Icon {

private static final long serialVersionUID = 1L;

private int size = 80, halfSize = 40;

private final BufferedImage image;

private Map components = new WeakHashMap();

public MouseAwareIcon() {
image = createImage();

public int getIconHeight() {
return image.getHeight();

public int getIconWidth() {
return image.getWidth();

public void mouseClicked(MouseEvent event) {
Object source = event.getSource();
if (source instanceof Component) {
Component component = (Component) source;
Point paintPoint = components.get(component);
if (paintPoint == null) {
System.out.println("unknown component");
} else {
Point mousePoint = event.getPoint();
int imageX = mousePoint.x - paintPoint.x;
int imageY = mousePoint.y - paintPoint.y;
if (imageX >= 0 && imageX < this.getIconWidth() && imageY >= 0
&& imageY < this.getIconHeight()) {
int argb = image.getRGB(imageX, imageY);
int alpha = (argb << 0) >>> 24;
int red = (argb << 8) >>> 24;
int green = (argb << 16) >>> 24;
int blue = (argb << 24) >>> 24;
System.out.println("Color clicked on "
+ component.getName() + ": " + alpha + ","
+ red + "," + green + "," + blue);
int fillX = halfSize * (imageX / halfSize);
int fillY = halfSize * (imageY / halfSize);
Graphics2D g2 = image.createGraphics();
g2.setColor(new Color(255 - red, 255 - green,
255 - blue, alpha));
g2.fill3DRect(fillX, fillY, halfSize, halfSize, true);
} else {
System.out.println("Clicked outside image area");

public void paintIcon(Component component, Graphics g, int x, int y) {
((Graphics2D) g).drawImage(image, null, x, y);
if (!components.containsKey(component)) {
components.put(component, new Point(x, y));

private BufferedImage createImage() {
BufferedImage image = new BufferedImage(size, size,
Graphics2D g2 = image.createGraphics();
Color[] colors = new Color[] { Color.BLACK, Color.RED, Color.GREEN,
Color.BLUE };
int colorIndex = 0;
for (int x = 0; x < size; x += halfSize) {
for (int y = 0; y < size; y += halfSize) {
g2.fill3DRect(x, y, halfSize, halfSize, true);
return image;


public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {

public void run() {
final JFrame frame = new JFrame();
JLabel label = new JLabel(new MouseAwareIcon());
frame.setSize(200, 200);



Hope this helps


Joined: 2007-05-28

OK you can do it as a JButton.

JButton paints the hexagons
MouseListener listens to JButton
MouseListener retrieves the Point from MouseEvent
Custom Logic you write calculates which hexagon was clicked on.

you can do it! It just seems hard!

Joined: 2007-05-28

Dont' add them as straight ImageIcons- add them as JLabels. They'll look the same, but they'll be able to accept mouse listeners.