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

时间:2017-04-25 06:51:53

标签: java swing

我需要一些帮助来练习我的Java类。我想要做的是当我点击JFrame的任何部分时,图像移近指针。现在我已经完成了这个部分,一旦我点击JFrame,图像与指针处于相同的位置,但它确实像是“远程移植”,我试图让它更像是指针位置的不断移动。

到目前为止,这是我的代码:

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

关于如何这样做的任何想法?我在想可能使用Thread但我不知道如何在这里实现它:s

3 个答案:

答案 0 :(得分:2)

这是一种非常简单的方法,基本上所有这一切都是使用Swing Timer将实体移向最后一个已知点击点

看看

了解更多详情

Swing不是线程安全的,在执行这些类型的操作时,考虑到这一点很重要。 Swing API提供了几种工作线程的方法,在这种情况下,我使用了一个简单的Timer,因为它定期生成更新并触发EDT内的更新,从而可以安全地更新UI来自

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

        }

    }
}

为什么不使用JLabel?很多原因JLabel并不适合这项任务,因为它需要考虑很多其他信息。这个例子也变成了#34;精灵朝向点击点,这是JLabel无法轻易实现的。

原则上,理论对于移动组件仍然是相同的。

有关此方法如何工作的更多详细信息

答案 1 :(得分:0)

在鼠标移动时重绘圆圈

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

答案 2 :(得分:0)

如果您想在每次点击时稍微移动标签,可以执行以下操作:

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

否则使用Hannes的计时器或MadProgrammer提供的the link