I have a frame with an image covering it, And i want that every time some one clicks on a different object in the image , it will act as a button and do something.
The problem is , Is that those objects are not simple shapes, so i was thinking about drawing my own invisible buttons in the shape of those objects.
Is that possible? or what would be a better way to accomplish such a thing?
-thank you
Concept: invisible buttons with circular and polygonal dispatch areas
First, you'll want a class defining an invisible button, extending javax.swing.AbstractButton
so that it's still a fully functional button that you can add listeners to.
public abstract class InvisibleButton extends AbstractButton {
public abstract boolean contains(Point point);
@Override
public boolean isVisible() {
return false;
}
}
Then, of course, you'll want implementations of that class. Here's 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'll need to implement a container that handles all of these buttons, but you should use a panel instead of a frame. Rather than hook each individual listener, you can simply override the frame's event processors and pass them to the necessary 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'll probably want to rename the panel to something less bulky, and maybe implement your own advanced image code, but that's the basic idea behind it.
Can you track the users mouse position via Coordinates?
PointerInfo a = MouseInfo.getPointerInfo();
Point b = a.getLocation();
int x = (int)b.getX();
int y = (int)b.getY();
Now put a ActionPerformed Method and test if x and y = e.g. 200, 300 do this. That way when a user clicks on a spot (your aiming for area) it will redirect him to a method.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With