So what I want to do is after one click is keep the mousePressed method 'on' even though im not holding it down myself. Then after another click it will turn it 'off'
addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent e) {
// save coord x,y when mouse is pressed
oldX = e.getX();
oldY = e.getY();
}
});
addMouseMotionListener(new MouseMotionAdapter() {
public void mouseDragged(MouseEvent e) {
// coord x,y when drag mouse
currentX = e.getX();
currentY = e.getY();
if (g2 != null) {
// draw oval if g2 context not null
g2.drawOval(oldX, oldY, width, height);
g2.fillOval(oldX, oldY, width, height);
// refresh draw area to repaint
repaint();
// store current coords x,y as olds x,y
oldX = currentX;
oldY = currentY;
}
}
});
Handle the mousePressed() event. Then keep a variable in your class (lets say "clickCounter") that you increment every time the event is generated.
Then you will need to handle the mouseMoved() event to know when the mouse is moving.
So now your logic in the mouseMoved() event can check if the variable is odd, which would indicate the mouse has just been clicked:
if (clickCounter % 2 == 1)
{
add your logic here
}
Or you could keep a boolean variable that you toggle off/on for every mouse click.
Related
This is a sample of a larger program used to draw rectangles. A rectangle object is drawn on screen already. what I am attempting to do with the mousedPressed object is get the coordinates of the mouse, and compare it with that of the rectangle's (which are initially set to (100, 100, 200, 200)). The mouseDragged event should take the coordinates obtained in the mousePressed section and run code with them; however, it seems that no matter what, the coordinates are always 0 in the mouseDragged event. I added test code (as marked) to each event to simply change the color of the square when the coordinates are at a certain point. The test code in mousedPressed works just fine, but the test code in mouseDragged can never run. I have tried with many, many different values, and determined that the coordinates will always equal 0 in the mouseDragged event. If someone could help me understand why the int values are not being passed, despite referencing the same variable, I would appreciate it.
public class PointListener implements MouseListener, MouseMotionListener {
private int mousex, mousey;
//in case that a user presses using a mouse,
//record the point where it was pressed.
public void mousePressed (MouseEvent event) {
//getPoint() returns a Point object containing the x & y-coordinates
currentPoint = event.getPoint();
mousex = event.getPoint().x;
mousey = event.getPoint().y;
repaint();
if (mousex > 250) {
currentColor = Color.GREEN;
repaint();
} //The test, which can easily be triggered as expected
}
public void mouseClicked(MouseEvent event) {}
public void mouseReleased(MouseEvent event) {}
public void mouseEntered(MouseEvent event) {}
public void mouseExited(MouseEvent event) {}
public void mouseMoved(MouseEvent event) {}
public void mouseDragged(MouseEvent event) {
if (95 < mousex && mousex < 105) {
currentColor = Color.BLUE;
repaint();
}
if (mousex > 150) {
currentColor = Color.RED;
repaint();
} // The test, which can never be triggered
} //mouseDragged()
} //PointListener
I am writing a 'sketchPad' type program in Java. My FREEHAND and LINE implementation works fine, but when I do a RECT or an OVAL if I draw from top left to bottom right it works fine, but the opposite way doesn't function. It will draw from my starting point then down to the bottom right again depending on the size I try to draw. I have learned a little bit about Affine Transform and thought that may be a way to go, but I need help implementing it properly, or doing it a better way.
Here is the effected portion of the code:
public void paint(){
addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent e) {
oldX = e.getX();
oldY = e.getY();
graphics2D.setPaint(toolBar.getCurrentColor());
repaint();
}
});
addMouseListener(new MouseAdapter() {
public void mouseReleased(MouseEvent e) {
String currentPaintType = toolBar.getPaintType();
if(currentPaintType != "FREEHAND"){
currentX = e.getX();
currentY = e.getY();
if(currentPaintType == "LINE"){
if (graphics2D != null){
graphics2D.drawLine(oldX, oldY, currentX, currentY);
}
}else if(currentPaintType == "OVAL"){
if (graphics2D != null){
graphics2D.drawOval(oldX, oldY, getWidthHeight(oldX,currentX), getWidthHeight(oldY,currentY));
}
}else if(currentPaintType == "RECT"){
if (graphics2D != null){
graphics2D.drawRect(oldX, oldY, getWidthHeight(oldX,currentX), getWidthHeight(oldY,currentY));
}
}
repaint();
}
}
});
}
//Code to calculate the proper width and height based on X/Y points
public int getWidthHeight(int old, int current){
int i=0;
if(old>current){
i=old-current;
}else{
i=current-old;
}
return i;
}
Right now I am trying to get it so whenever I click inside of the oval that I have painted, and drag the mouse it will move positions by repainting. However, even though the MouseEvents are being detected correctly, the oval image is not updating. I am confused to why that is. Here is the code that deals with the oval, MouseEvents, and updating:
public class DrawOval extends JPanel {
private int size = 50;
private int locX = 0; //vector points
private int locY = 0;
private boolean isPressed = false;
private Shape oval = new Ellipse2D.Double(locX, locY, size, size * 2);
public DrawOval(int size){
this.size = size;
Dimension dims = new Dimension(size, size);
setPreferredSize(dims);
setMaximumSize(dims);
setMinimumSize(dims);
MouseAdapter m = new MouseAdapter(){
public void mouseReleased(MouseEvent e){
isPressed = false;
update(e);
System.out.println("Mouse is released!");
}
public void mousePressed(MouseEvent e){
isPressed = true;
update(e);
System.out.println("Mouse is pressed!");
}
public void mouseDragged(MouseEvent e){
if(isPressed){
update(e);
System.out.println("Mouse is dragged!");
}
}
public void update(MouseEvent e){
System.out.println("X: " + e.getX() + ", Y: " + e.getY());
if(oval.contains(e.getX(), e.getY())){
setX(e.getX()); setY(e.getY());
repaint();
}
//does not update if the mouses click coordinates are outside of the oval
}
};
addMouseListener(m); //for pressing and releasing
addMouseMotionListener(m); //for dragging
}
public void setX(int _x){
this.locX = _x;
}
public void setY(int _y){
this.locY = _y;
}
public void paintComponent(Graphics g){
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.setColor(Color.BLACK);
g2.fill(oval);
}
}
I cannot figure out why it is not updating correctly. I had it partially working before, but it would update all the time, even if where the user clicked was not within the oval.
I think doing setX and setY you forget to update x and y in your oval. You have at least three options:
1) recreate Ellipse2D.Double every time you change this.locX and this.locY.
2) expect that your oval is created with x=0, y=0 once and for all, check mouse event switching to relative coordinates (if(oval.contains(e.getX() - locX, e.getY() - locY)){...}) and draw your oval using AffineTransform by g2.transform(...).
3) Declare oval as Ellipse2D.Double oval = new Ellipse2D.Double(...); and then you can change its x and y directly cause they're public:
oval.x = this.locX;
oval.y = this.locY;
I made a GUI application but I am stuck with a workaround algorithm to drag/move ui element relatively to another surface (screen, canvas, etc.). In my case I use it for a window relative to the screen, but that's beside the point because this algorithm should work anywhere possible. Here is my algorithm:
code-listing-1.
MouseMotionAdapter(){
int prevX = -1000, prevY = -1000, getX, getY;
public void mouseDragged(MouseEvent e) {
//if initial cursor position isn't set
if(prevX==-1000){
prevX = e.getLocationOnScreen().x;
prevY = e.getLocationOnScreen().y;
getX = e.getX();
getY = e.getY();
}
//move element to new position
theFrame.setBounds(theFrame.getBounds().x+e.getX()-getX, theFrame.getBounds().y+e.getY()-getY, 880, 583);
prevX=e.getLocationOnScreen().x;
prevY=e.getLocationOnScreen().y;
}
The trouble with this algorithm is that the mouse cursor position is definitely fixed relatively to the element and if I try to move/drag the element clicking in another position/part of the element the whole element moves so that the mouse cursor is positioned at the "initial position", which is not the behaviour I want (I want it to have the behaviour we mostly know like when we move an icon on desktop or a window on the screen, etc.)
Can anyone help with that? Thanks in advance.
The usual approach in such a case is to compute the difference between the current and the previous position. This difference is then "the movement", that is added to the position of the dragged object.
(BTW: You seem to not use the prev... values in your computation at all!)
Inside a MouseMotionListener, this could roughly look as follows:
class MouseDraggingControl implements MouseMotionListener
{
private Point previousPoint = new Point();
#Override
public void mouseMoved(MouseEvent e)
{
previousPoint = e.getPoint();
}
#Override
public void mouseDragged(MouseEvent e)
{
int movementX = e.getX() - previousPoint.x;
int movementY = e.getY() - previousPoint.y;
doMovement(movementX, movementY);
previousPoint = e.getPoint();
}
}
In your case, the doMovement method might be implemented like this:
private void doMovement(int movementX, int movementY)
{
int oldX = theFrame.getX();
int oldY = theFrame.getY();
int newX = oldX + movementX;
int newY = oldY + movementY;
theFrame.setLocation(newX, newY);
}
(or similar, using the getBounds/setBounds calls)
EDIT If the mouse motion listener is attached directly to the component that should be dragged, you might have to use the "location on screen" instead:
class MouseDraggingControl implements MouseMotionListener
{
private Point previousPoint = new Point();
#Override
public void mouseMoved(MouseEvent e)
{
previousPoint = e.getLocationOnScreen();
}
#Override
public void mouseDragged(MouseEvent e)
{
Point p = e.getLocationOnScreen();
int movementX = p.x - previousPoint.x;
int movementY = p.y - previousPoint.y;
doMovement(movementX, movementY);
previousPoint = e.getLocationOnScreen();
}
}
If this does not solve your issue, I'd like to emphasize the comment from MadProgrammer: An example that demonstrates your actual problem would help here.
I put a aintComponent() method in a JPanel. This method draws a tree using Graphics.drawLine().
I put a JButton from which a Listener is used to zoom on this tree. At the end I use the repaint() method, and my tree is repainted bigger, so no problem there.
// Add Listeners on Zooming buttons
bPlus.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent event){
Node.setZoom(1);
repaint();
}
});
However, I used a MouseMotionListener for moving this tree inside its JPanel.
Then when I call repaint(), it does not erase the previous printed trees, so I end up with duplicated trees.
addMouseMotionListener(new MouseMotionAdapter() {
public void mouseDragged(MouseEvent e) {
if(mouseHolded) {
x += e.getX() - mouseX;
mouseX = e.getX();
y += e.getY() - mouseY;
mouseY = e.getY();
repaint(); // <===
}
}
}
);
What am I doing wrong ? While the previous trees will be erased when I use the repaint() for zooming, why wont it do so when I move the tree?