0

i need some help here with an exercise of my Java class. What i'm trying to do is that when i click on any part of the JFrame, an image moves closer to the pointer. Right now i have done the part that once i click on the JFrame the image is in the same position as the pointer but it does like it's "teleporting" and i'm trying to make it more like a constant movement to the pointer position.

So far this is my code i have atm:

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class ControlaRaton extends MouseAdapter {
  JLabel label;

  public ControlaRaton(JLabel label){
    this.label = label;
  }

  public void mouseClicked(MouseEvent evt){
    Point pos = evt.getPoint();
    System.out.println(pos.x+" "+pos.y);
    //System.out.println("Boton: "+evt.getButton());
    label.setLocation(pos.x-20,pos.y-50);
  }
}

Any ideas on how to do it that way? I was thinking maybe using a Thread but i don't know exactly how to implement it here :s

G.S
  • 10,413
  • 7
  • 36
  • 52
Space_Shift
  • 83
  • 11
  • Do you want the image to move slowly to the point were you clicked till it reaches the click-position with only one click? Or do you want to it to move a bit each time you click? – M. Haverbier Apr 25 '17 at 07:02
  • Possible duplicate [Move image towards mouse position](http://stackoverflow.com/questions/26784303/java-move-image-towards-mouse-position/26791886#26791886) – MadProgrammer Apr 25 '17 at 07:10
  • @M.Schwarzer-Haverbier move slowly to the point were i clicked with the mouse until it reaches the click-position with one click – Space_Shift Apr 25 '17 at 21:11

3 Answers3

2

This is pretty simple approach, basically all this does is uses a Swing Timer to move an entity towards the last known click point

Have a look at

for more details

Swing is NOT thread safe, when performing these types of operations, it's important to take this into consideration. The Swing API provides several ways to work threads, in this case, I've used a simple Timer as it generates updates at a regular interval and triggers updates from within the EDT, making it safe to update the UI from within

Follow the sounds

import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class MoveTowards {

    public static void main(String[] args) {
        new MoveTowards();
    }

    public MoveTowards() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new MoveTowardsPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    class MoveTowardsPane extends JPanel {

        private final BufferedImage image;
        private Point imagePosition = new Point(150, 150);
        private Point mousePoint;
        private double imageAngleRad = 0;

        public MoveTowardsPane() {
            BufferedImage i = null;
            try {
                i = ImageIO.read(getClass().getResource("/sprite.png"));
            } catch (IOException e) {
                e.printStackTrace();
            }
            image = i;
            addMouseListener(new MouseAdapter() {
                @Override
                public void mouseClicked(MouseEvent e) {
                    mousePoint = e.getPoint();
                    double dx = e.getX() - imagePosition.getX();
                    double dy = e.getY() - imagePosition.getY();
                    imageAngleRad = Math.atan2(dy, dx);

                    repaint();
                }
            });

            Timer timer = new Timer(40, new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    if (mousePoint != null) {

                        int centerX = imagePosition.x + (image.getWidth() / 2);
                        int centerY = imagePosition.y + (image.getHeight() / 2);

                        if (mousePoint.x != centerX) {
                            imagePosition.x += mousePoint.x < centerX ? -1 : 1;
                        }
                        if (mousePoint.y != centerY) {
                            imagePosition.y += mousePoint.y < centerY ? -1 : 1;
                        }
                        repaint();
                    }
                }
            });
            timer.start();
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(400, 400);
        }

        @Override
        protected void paintComponent(Graphics gr) {
            super.paintComponent(gr);
            Graphics2D g = (Graphics2D) gr.create();
            g.setRenderingHint(
                RenderingHints.KEY_RENDERING,
                RenderingHints.VALUE_RENDER_QUALITY);

            int cx = image.getWidth() / 2;
            int cy = image.getHeight() / 2;
            AffineTransform oldAT = g.getTransform();
            g.translate(cx + imagePosition.x, cy + imagePosition.y);
            g.rotate(imageAngleRad);
            g.translate(-cx, -cy);
            g.drawImage(image, 0, 0, null);
            g.setTransform(oldAT);
            g.dispose();

        }

    }
}

Why doesn't this use a JLabel? A lot of reasons, JLabel isn't really well fitted for the task, as it needs to take into account a lot of other information. This example also "turns" the sprite towards the click point, something which isn't easily achieved with a JLabel.

In principle, the theory is still the same for moving a component.

See

for more details about how this approach works

MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
0

Redraw your circle on mouse move

    void mouseMoved(MouseEvent evt){
          Point pos = evt.getPoint();
System.out.println(pos.x+" "+pos.y);
//System.out.println("Boton: "+evt.getButton());
label.setLocation(pos.x-20,pos.y-50);
     }
});
Jay Smith
  • 2,331
  • 3
  • 16
  • 27
  • OP already have the "teleporting" image on mouse event (click). He is looking for a smooth movement of the image to the click location – AxelH Apr 25 '17 at 07:03
0

If you want to move the label just a bit with each click you could do the following:

public void mouseClicked(MouseEvent evt){
  Point clickedPos = evt.getPoint();
  Point newPosForLabel = calculateNewPos(clickedPos, labelPos);
  label.setLocation(newPosForLabel);
}

private Point calculateNewPos(Point clickedPos, Point labelPos) {
  // calculate newPos based on labelPos and clickedPos
  return newPos;
}

else use the timer from Hannes or from the link given by MadProgrammer:

Community
  • 1
  • 1
M. Haverbier
  • 383
  • 2
  • 13