Gap between mouse on screen and JPanel on Dragndrop - java

I use JPanel to draw a square on the screen.
When I use MouseDragged it works fine and goes wherever I want, almost. Each time I click on the square, the square automatically moves and the top left corner goes right under the mouse.
How should I do so that the square doesn't replace itself and stays right under the mouse ?
Thanks for any help.

Keep an account of the difference between top-left coordinates of Component which you are
moving and mousePressed location.
And when you get new position, just subtract that difference to it.
Here I have tried to explain it through coding. Let myJPanel be the component you want to
move. Then here is the MouseAdapter that can work for you. New position is stored in
newPosition variable.
new MouseAdapter(){
int diffx = 0, diffy = 0;
public void mousePressed(MouseEvent e) {
Point topLeft = myJPanel.getLocation();
Point mouseDn = e.getPoint();
diffx = mouseDn.x - topLeft.x;
diffy = mouseDn.y - topLeft.y;
}
public void mouseDragged(MouseEvent e) {
Point mouseDr = e.getPoint();
int newX = mouseDr.x - diffx;
int newY = mouseDr.y - diffy;
Point newPosition = new Point(newX, newY);
}
};

Related

Mouse Drag To Zoom implementation Java - not on click

I have written some code to implement a drag to zoom (i.e. draw a rectangle with the mouse and then zoom into this area so it fills the container) on a JPanel. However, before I wrote this into the Listener, I had a "mouseClicked" method, which is still there. This method performed a different function, simply returning the coords of the click.
Unfortunately, I mistakenly implemented the zoom function using MousePressed, which thus runs at the same time as the mouseClicked event. This means that when I click the mouse to get the coordinates, it also zooms in on a very small rectangle. Is there anyway to change this?
Thanks in advance for any suggestions, and please let me know if you need anything clarifying!
Here is the listener class:
class panelClickListener extends MouseAdapter implements MouseMotionListener {
JLabel toShowCoords, rangeLabel;
juliaPanel panelJulia;
mandPanel panelMand;
int startX, startY, currentX, currentY;
boolean dragging;
ComplexNumber startRange, endRange;
public panelClickListener(JLabel toShowCoordsIn, juliaPanel panelJuliaIn, mandPanel panelMandIn, JLabel rangeLabelIn) {
toShowCoords = toShowCoordsIn;
panelJulia = panelJuliaIn;
panelMand = panelMandIn;
rangeLabel = rangeLabelIn;
}
public void mouseClicked(MouseEvent e) {
int x = e.getX();
int y = e.getY();
userSelectedPoint = pointsToDrawOn[x][y];
toShowCoords.setText("Number Selected: " + userSelectedPoint.getReal() + " , " + userSelectedPoint.getImaginary());
panelJulia.setFixedNumber(pointsToDrawOn[x][y]);
panelJulia.repaint();
}
public void mousePressed(MouseEvent event) {
Point point = event.getPoint();
startX = point.x;
startY = point.y;
dragging = true;
}
public void mouseReleased(MouseEvent event) {
dragging = false;
startRange = pointsToDrawOn[startX][startY];
endRange = pointsToDrawOn[currentX][currentY];
maxVal = endRange;
minVal = startRange;
rangeLabel.setText("Real axis: " + minVal.getReal() + "," + maxVal.getReal() + " - Imaginary axis: " + minVal.getImaginary() + "," + maxVal.getImaginary());
populatePointArray();
panelMand.repaint();
}
public void mouseDragged(MouseEvent event) {
Point p = event.getPoint();
currentX = p.x;
currentY = p.y;
}
}
dragging should only be set to true when mouseDragged is called, then when mouseReleased is called, you need to check to see if dragging is true before processing the zoom
There's some theory to go with that, mouseClicked will only be called if the point of the mouse is the same for mousePressed and mouseReleased.
So in a click operation you can expect mousePressed, mouseReleased and mouseClicked to be called (I believe in that order, but you'd better test it).
In a drag operation, you can expect mousePressed, mouseDragged and mouseReleased to be called

Rotating a PVector

ok guys i want to rotate a PVector that i have in this method.
this method replaces the posX and posY by the x and y of the PVector.
the movement is determinated by a joystick that comes from arduino it moves the image in x and y but i would like to turn the vector depending on the axis the joystick is looking
public void moverPjUno(PVector coordenadas) {
if(areaXad==-1 && areaXat==-1){
miPersonaje.setPosX((miPersonaje.getPosX())+(int)coordenadas.x);
}
if(areaYab==-1 && areaYar==-1){
miPersonaje.setPosY((miPersonaje.getPosY())+(int)coordenadas.y);
}
}
I don't have an Arduino hooked up and I don't know what kind of information your joystick is giving you, so I made a Processing example that uses the mouse to imitate the joystick:
int rad = 100;
void setup() {
size(400, 400);
}
void draw() {
background(255);
ellipse(width/2, height/2, rad*2, rad*2);
// Using the mouse to mimic the position of the joystick
float theta = atan2(mouseY-height/2, mouseX-width/2);
// Get the new position
float x = width/2+cos(theta)*rad;
float y = height/2+sin(theta)*rad;
// Show the new position
ellipse(x, y, 30, 30);
}
The atan2 function gives the angle to the mouse position, replace the arguments with the equivalent of the joystick position. The smaller ellipse being drawn shows where your miPersonaje would be set based on x and y earlier in the code. The rad variable is arbitrary and just for displaying purposes, you can set it to be whatever you want (if needed at all).

Finding Mouse Position relative to a panel

I'm trying to get the mouse's position within a panel, as in the top left of the panel = x/y 0,0.
What I have at the minute gives the position on the entire screen, so depending on where the panel (which is in a frame) is on the screen, the coordinates are different. I guess you could add to the x/y co-ordinates to account for this, but this seems like a messy solution. Can anyone help?
Here's the mouseListener I'm using, which has been added to the panel.
private class MouseListener extends MouseAdapter
{
public void mouseClicked(MouseEvent e)
{
// Finds the location of the mouse
PointerInfo a = MouseInfo.getPointerInfo();
Point b = a.getLocation();
// Gets the x -> and y co-ordinates
int x = (int) b.getX();
int y = (int) b.getY();
System.out.println("Mouse x: " + x);
System.out.println("Mouse y: " + y);
// Determines which tile the click occured on
int xTile = x/tileSize;
int yTile = y/tileSize;
System.out.println("X Tile: " + xTile);
System.out.println("Y Tile: " + yTile);
}
}
See MouseEvent.getPoint().
Returns the x,y position of the event relative to the source component.
You can use MouseEvent.getX() and MouseEvent.getY() to get the relative co-ordinates of X & Y respectively.
int relativeX = e.getX();
int relativeY = e.getY();
...

Manipulate Arc with mouse (JavaFX 2)

I have a problem to manipulate an Arc shape in javafx with mouse drag events
I have an Arc defined with the following paramters:
radiusX and radiusY :horizontal and vertical radius of the full ellipse of which this arc is a partial section
centerX,centerY : center point of the Arc
startAngle: starting angle of the arc (relative to the horizontal axis)
length: angular extent of the arc in degrees
So what i need is to make the start angle of the arc "follow" the mouse movement while dragging:
when the user press on the starting point of the Arc (located on the startAngle) and while dragging the mouse i need to compute the new starting angle formed by the horizontal axis and the line from the center to the mouse position
Basically the problem is to compute the start angle of the arc given a point (the mouse position) and the other given parameters (center, major and minor axis)
What i'm doing actuyally is calculating the angle with the Math.atan2 function
newStartAngle = atan2(xMouse, yMouse) (assume center x, y at 0,0)
but it works only if the arc is circular (radiusX = radiusY)
Another way to put it is : i need the start point of the arc to be always on the line from the center to the mouse position (so i need to continually update the start angle in order to make it follow the mouse rotation movement). (i hope i've made it a little clear)
Here is the complete source of a sample
import javafx.stage.Stage;
...
public class Main extends Application {
#Override
public void start(Stage primaryStage) {
Pane pane = new Pane();
Group designer = createDesigner();
designer.setLayoutX(100);
designer.setLayoutY(200);
pane.getChildren().add(designer);
Scene sc = new Scene(pane, 600, 600);
primaryStage.setScene(sc);
primaryStage.show();
}
public static final double RX = 100;
public static final double RY = 50;
public static final double S_ANGLE = 45;
public static final double ARC_LENGTH = 90;
private Arc arc;
private Circle handle;
private Line connection;
double xMouse,yMouse;
public Group createDesigner() {
arc = new Arc();
arc.setRadiusX(RX);
arc.setRadiusY(RY);
arc.setStartAngle(S_ANGLE);
arc.setLength(ARC_LENGTH);
arc.setFill(Color.LIGHTBLUE);
arc.setType(ArcType.ROUND);
handle = new Circle();
handle.setRadius(5);
handle.setStroke(Color.BLACK);
handle.setFill(Color.TRANSPARENT);
handle.setCenterX(
RX * Math.cos(Math.toRadians(S_ANGLE))
);
handle.setCenterY(
-RY * Math.cos(Math.toRadians(S_ANGLE))
);
connection = new Line();
connection.startXProperty().bind(arc.centerXProperty());
connection.startYProperty().bind(arc.centerYProperty());
connection.endXProperty().bind(handle.centerXProperty());
connection.endYProperty().bind(handle.centerYProperty());
handle.setOnMouseDragged(new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent event) {
xMouse = event.getX();
yMouse = event.getY();
handle.setCenterX(xMouse);
handle.setCenterY(yMouse);
double angleInRadians = Math.atan2(-yMouse, xMouse);
arc.setStartAngle(Math.toDegrees(angleInRadians));
}
});
return new Group(arc, connection, handle);
}
public static void main(String[] args) {
launch(args);
}
}
Thank you in advance
well i solved it, suffice to divide xMouse and yMouse by major and minor axe to make it work
newStartAngle = Math.atan2(-yMouse/radiusY, xMouse/radiusX)
//assume center x, y at 0,0

Dragging A Circle on a JFrame

I am trying to have a circle appear on the screen, then when the user clicks INSIDE the circle, enable the ability for them to drag the circle where the mouse goes while it is being pressed.
This is the code i have so far, the drag works, but it is allowing the user to drag without them pressing the inside of the circle, just when anywhere on the screen is pressed.
I hope i am not too confusing
here's the code i have, please if someone could just tell me the code that needs to be corrected, it will save me anymore hours.
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class DragCircle extends JFrame {
private static final long serialVersionUID = 1L;
public static int size = 400;
public static int r = 10;
private int x;
private int y;
private int cX;
private int cY;
private int dX;
private int dY;
private MouseHandler mh;
boolean isCircleClicked = false;
public static void main(String[] args) {
DragCircle c1 = new DragCircle();
c1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public DragCircle() {
super("Drag circle");
cX = r + 100;
cY = r + 100;
mh = new MouseHandler();
addMouseListener(mh);
addMouseMotionListener(mh);
setSize(size, size);
setVisible(true);
}
public void paint(Graphics g) {
super.paint(g);
g.setColor(Color.RED);
g.fillOval(cX, cY, r * 2, r * 2);
}
private class MouseHandler extends MouseAdapter implements
MouseMotionListener {
public void mousePressed(MouseEvent me)
{
if ((cX - me.getX()) * (cX - me.getX()) + (cY - me.getY())
* (cY - me.getY()) < r * r) {
isCircleClicked = true;
}
}
public void mouseDragged(MouseEvent me) {
if (isCircleClicked) {
x = me.getX() - dX;
y = me.getY() - dY;
cX = x + r;
cY = y + r;
repaint();
}
}
public void mouseReleased(MouseEvent e) {
isCircleClicked = false;
}
}
}
Your one problem is with
public void mouseDragged(MouseEvent me) {
if (isCircleClicked = true) {
What you're doing here is setting isCircleClicked to true every time you drag the mouse. Also this statement evaluates to true which is why you can drag anywhere and move the circle. Change this to
if (isCircleClicked) {
and you should be fine here.
The next problem is that you never reset isCircleClicked to false. You should be doing this either in mouseReleased or change your mousePressed as follows:
public void mousePressed(MouseEvent me) {
isCircleClicked =
(cX - me.getX()) * (cX - me.getX()) +
(cY - me.getY)) * (cY - me.getY()) < r * r;
}
which will set isCircleClicked accordingly.
There is still something to do, though. In the current form you need to start dragging to the upper-left of the center point, as illustrated below:
+------+
| |
| .-|-.
| / | \
+------+ |
\ /
'-_-'
This is because of your drawing: fillOval takes an upper-left corner of the oval and a width and height of the bounding rectangle. It's not the center point and the respective diameters. Hence you need to adapt his as follows:
g.fillOval(cX - r, cY - r, r * 2, r * 2);
Note the offset by the radius to the left and top.
Furthermore, your dragging code needs a bit more work. You are currently assuming that the user drags the circle's center. What you need to do is save the coordinates of the mouse click and then move the circle based on the mouse's movement relative to the last point. Currently you're moving relative to the circle's center so for the movement to be nice you have to start dragging exactly in the center of the circle. I'll leave that as an exercise for you :-)
Besides, your listener class already inherits from MouseAdapter so you don't need to explicitly implement the MouseMotionListener since MouseAdapter implements it already.
The structure of you program is wrong. You should never override the paint(...) method of a JFrame. That is an old AWT trick and should NOT be used with Swing.
Read the section from the Swing tutorial on Custom Painting for an example of the proper way to do painting. The basics are to override the paintComponent(...) method of a JPanel and then add the panel to the content pane of the frame.
With regards to you question a better solution is to create an Elllipse2D object to represent your circle. Then the custom painting can use the drawShape(...) method of the Graphics2D class. Then in you MouseListener code you can use the Shape.contains(...) method to see if the mouse was clicked on the circle.

Categories