How to create a complex button shape?

I have a frame with an image covering it. And I want every time someone clicks on another object in the image, he will act like a button and do something. The problem is that these objects are not simple forms, so I thought about drawing my own invisible buttons in the form of these objects.

Is it possible? or what would be the best way to achieve this?

-from you

+6
source share
4 answers

Define an interface for the scope, for example:

//represents any clickable area. public interface IButton{ boolean contains(int x, int y); } 

Then, if you want the circular area to be clickable, define a class that checks if the x, y coordinate is at some distance from the position.

 public class CircleButton implements IButton{ Point center; double radius; public CircleButton(int x, int y, double radius){ this.center = new Point(x,y); this.radius = radius; } //check if x,y coords are within a radius //from the center of this circle button public boolean contains(int x, int y){ double dx = x-center.x; double dy = y-center.y; return (Math.sqrt(dx*dx+dy*dy) <= radius); } } 

Create a list of IButtons. You will iterate over them to see if the user clicked one of your invisible buttons.

 List<IButton> buttons = new List<IButton>(); buttons.add(new CircleButton(100,100,200); 

Then, every time someone clicks on your frame, iterate over your invisible buttons using the location of this mouse click.

 public void mouseReleased(MouseEvent e){ for(IButton b : buttons){ if(b.contains(evt.getX(),e.getY()){ //do something depending on what button was clicked. } } } 

You can easily see how you could define invisible rectangle buttons like this, or even irregular polygon shapes. You just need to correctly implement the contains method.

+3
source

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.

+3
source

Is it possible to track the user's mouse position through coordinates?

  PointerInfo a = MouseInfo.getPointerInfo(); Point b = a.getLocation(); int x = (int)b.getX(); int y = (int)b.getY(); 

Now put the ActionPerformed method and check if x and y = for example. 200, 300 do it. Thus, when the user clicks on a point (your goal for the area), it redirects it to the method.

+2
source

And I want every time someone clicks on another object in the image, he will act like a button and do something.

You can create an ArrayList of Shape objects. Then you add the MouseListener to the component containing the image. Whenever the mousePressed event is raised, you loop through an ArrayList and use the component's containsts (...) method to determine if the user clicks on the corrdinates shapes.

Check out Game with figures . The code will not help with your immediate problem, but it will give you an idea of ​​the type of Shapes that you can define.

+2
source

Source: https://habr.com/ru/post/951339/


All Articles