Concept: invisible buttons with circular and polygonal sending areas
First you need a class that defines an invisible button, extending javax.swing.AbstractButton so that it is still a fully functional button to which you can add listeners.
public abstract class InvisibleButton extends AbstractButton { public abstract boolean contains(Point point); @Override public boolean isVisible() { return false; } }
Then, of course, you will need implementations of this class. Here are two examples: one using a polygon for complex shapes, one using a circle.
public class PolygonalButton extends InvisibleButton { private Polygon area = null; public PolygonalButton(Polygon area) { this.area = area; } @Override public boolean contains(Point point) { return area.contains(point); } } public class CircularButton extends InvisibleButton { private int x; private int y; private double radius; public CircularButton(int x, int y, double radius) { this.x = x; this.y = y; this.radius = radius; } @Override public boolean contains(Point point) { double dx = x - point.x; double dy = y - point.y; return Math.sqrt(dx * dx + dy * dy) <= radius; } }
Finally, you will need to implement a container that processes all of these buttons, but you should use a panel instead of a frame. Instead of connecting each individual listener, you can simply redefine the event processors of the frame and transfer them to the desired buttons.
public class InvisibleButtonImagePanel extends JPanel { private BufferedImage image = null; private List<InvisibleButton> buttons = new ArrayList<>(); public InvisibleButtonImagePanel(BufferedImage image) { this.image = image; } public void add(InvisibleButton button) { buttons.add(button); } public void remove(InvisibleButton button) { buttons.remove(button); } @Override public Dimension getPreferredSize() { return new Dimension(image.getWidth(), image.getHeight()); } @Override public void processKeyEvent(KeyEvent event) { for (InvisibleButton button : buttons) { if (button.isFocusOwner()) { button.dispatchEvent(event); } } super.processKeyEvent(event); } @Override public void processMouseEvent(MouseEvent event) { for (InvisibleButton button : buttons) { if (button.contains(event.getPoint())) { button.dispatchEvent(event); } } super.processMouseEvent(event); } @Override protected void paintComponent(Graphics g) { g.drawImage(image, 0, 0, null); super.paintComponent(g); } }
You will probably want to rename the panel to something more bulky and perhaps implement your own extended image code, but this is the main idea.
source share