How to create component clicks in Java swing?

I created a custom component that only shows a string. The line is drawn from the upper left corner to the lower right corner as Line2D according to the drawing method. The background is transparent. I have expanded JComponent. These linear components are draggable and change the color of the lines when the mouse pointer is max. 15 pixels from the drawn line. But if I have several of these components added to another custom component that extends JPanel, they sometimes overlap. I want to implement this, if the mouse pointer is more than 15 pixels from the line, the mouse events should go through the component. How to skip this is my problem. Is it possible?

Thanks in advance!

+4
source share
5 answers

During my last project at the university, I made a whiteboard program and had the same problem. For each shape that the user drew on the board, I created a JComponent, which was great when they drew rectangles, but harder with the free form tool.

The way I fixed it, in the end, was to completely destroy JComponents. I had a JPanel in which a vector (I think) of custom Shape objects was stored. Each object had its own coordinates and line thickness, etc. When the user clicked on the board, the mouse listener on the JPanel fired and went through each Shape, calling the a (int x, int y) method on each of them (x and y are the coordinates of the event). Since the shapes were added to the vector when they were drawn, I knew that the latter, to return true, was the topmost shape.

This is what I used for the straight line method contains. Math may be a bit, but it worked for me.

public boolean contains(int x, int y) { // Check if line is a point if(posX == endX && posY == endY){ if(Math.abs(posY - y) <= lineThickness / 2 && Math.abs(posX - x) <= lineThickness / 2) return true; else return false; } int x1, x2, y1, y2; if(posX < endX){ x1 = posX; y1 = posY; x2 = endX; y2 = endY; } else{ x1 = endX; y1 = endY; x2 = posX; y2 = posY; } /**** USING MATRIX TRANSFORMATIONS ****/ double r_numerator = (x-x1)*(x2-x1) + (y-y1)*(y2-y1); double r_denomenator = (x2-x1)*(x2-x1) + (y2-y1)*(y2-y1); double r = r_numerator / r_denomenator; // s is the position of the perpendicular projection of the point along // the line: s < 0 = point is left of the line; s > 0 = point is right of // the line; s = 0 = the point is along the line double s = ((y1-y)*(x2-x1)-(x1-x)*(y2-y1) ) / r_denomenator; double distance = Math.abs(s)*Math.sqrt(r_denomenator); // Point is along the length of the line if ( (r >= 0) && (r <= 1) ) { if(Math.abs(distance) <= lineThickness / 2){ return true; } else return false; } // else point is at one end of the line else{ double dist1 = (x-x1)*(x-x1) + (y-y1)*(y-y1); // distance to start of line double dist2 = (x-x2)*(x-x2) + (y-y2)*(y-y2); // distance to end of line if (dist1 < dist2){ distance = Math.sqrt(dist1); } else{ distance = Math.sqrt(dist2); } if(distance <= lineThickness / 2){ return true; } else return false; } /**** END USING MATRIX TRANSFORMATIONS****/ } 

posX and posY are the coordinates of the beginning of the line and endX, and endY is yep, the end of the line. This is returned if the click is within lineThickness / 2 of the center of the line, otherwise you need to click in the very middle of the line.

Drawing shapes is a case of passing each Shape to a JPanel Graphics object and drawing with it.

+2
source

I want to implement this if the mouse pointer is more than 15 pixels away from the line mouse events should go through the component.

If your child component has a mouse listener, it will intercept every mouse event that happens over it. If you want to redirect MouseEvent to the parent component, you must do this manually. For example, you can implement your custom mouse listener extending the MouseAdapter:

 public class yourMouseListener extends MouseAdapter{ //this will be called when mouse is pressed on the component public void mousePressed(MouseEvent me) { if (/*do your controls to decide if you want to propagate the event*/){ Component child = me.getComponent(); Component parent = child.getParent(); //transform the mouse coordinate to be relative to the parent component: int deltax = child.getX() + me.getX(); int deltay = child.getY() + me.getY(); //build new mouse event: MouseEvent parentMouseEvent =new MouseEvent(parent, MouseEvent.MOUSE_PRESSED, me.getWhen(), me.getModifiers(),deltax, deltay, me.getClickCount(), false) //dispatch it to the parent component parent.dispatchEvent( parentMouseEvent); } } } 
+3
source

It has been a while since I touched Swing, but I think you will need to handle the mouse events in the parent component, and then scroll through the child components using the lines and determine which one should handle the event (well, the decision logic should -still remain in the line component, but the parent will explicitly refer to this logic until one of the components accepts the event).

+2
source

I believe the easiest way is to catch the event and call parent.processEvent() . Thus, the component will be transparent to events, because it will distribute them to the parent.

+1
source

I struggled with this question and tried all things with parents and glass glass until I realized that overriding the contains method does exactly what you want. Because when a parent runs some kind of getcomponent , your "Line" will answer it: "no, it's not me, I'm not there!" and the loop checks other components. In addition, when you need to adjust the complex depth for your dragged object, you can use a descendant of JLayeredPane.

0
source

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


All Articles