简体   繁体   English

将图像移动到在JFrame上单击的光标位置

[英]Moving an image to the position of the cursor where is clicked on a JFrame

i need some help here with an exercise of my Java class. 我的Java类练习需要一些帮助。 What i'm trying to do is that when i click on any part of the JFrame, an image moves closer to the pointer. 我想做的是,当我单击JFrame的任何部分时,图像移近指针。 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. 现在,我已经完成了以下部分,一旦我单击JFrame,图像就会与指针处于相同的位置,但是它确实像是在“传送”,并且我试图使其更像是不断向指针位置移动。

So far this is my code i have atm: 到目前为止,这是我拥有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 我在想也许使用一个线程,但是我不知道确切如何在这里实现它:

This is pretty simple approach, basically all this does is uses a Swing Timer to move an entity towards the last known click point 这是非常简单的方法,基本上所有这些操作都是使用Swing Timer将实体移向最后一个已知的点击点

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. Swing不是线程安全的,因此在执行这些类型的操作时,请务必考虑到这一点。 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 Swing API提供了几种处理线程的方法,在这种情况下,我使用了一个简单的Timer因为它定期生成更新并从EDT内部触发更新,从而可以安全地从内部更新UI

跟随声音

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 ? 为什么不使用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. 有很多原因, JLabel并不是很适合该任务,因为它需要考虑很多其他信息。 This example also "turns" the sprite towards the click point, something which isn't easily achieved with a JLabel . 这个例子也将精灵“转向”了点击点,而使用JLabel很难实现。

In principle, the theory is still the same for moving a component. 原则上,移动零部件的理论仍然相同。

See 看到

for more details about how this approach works 有关此方法如何工作的更多详细信息

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);
     }
});

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: 否则,请使用Hannes或MadProgrammer提供的链接中的计时器:

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM