将图像移动到在 JFrame 上单击的光标位置 [英] Moving an image to the position of the cursor where is clicked on a JFrame

查看:43
本文介绍了将图像移动到在 JFrame 上单击的光标位置的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要一些帮助来练习我的 Java 课程.我想要做的是,当我单击 JFrame 的任何部分时,图像会移近指针.现在我已经完成了一旦我点击 JFrame 图像与指针处于相同位置的部分,但它确实像是传送",我试图让它更像是一个持续移动到指针位置.

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

import javax.swing.*;导入 java.awt.*;导入 java.awt.event.*;公共类 ControlaRaton 扩展 MouseAdapter {JLabel 标签;公共 ControlaRaton(JLabel 标签){this.label = 标签;}public void mouseClicked(MouseEvent evt){点 pos = evt.getPoint();System.out.println(pos.x+" "+pos.y);//System.out.println("Boton: "+evt.getButton());label.setLocation(pos.x-20,pos.y-50);}}

关于如何做到这一点的任何想法?我在想也许使用线程,但我不知道如何在这里实现它:s

解决方案

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

看看

  • import java.awt.Dimension;导入 java.awt.EventQueue;导入 java.awt.Graphics;导入 java.awt.Graphics2D;导入 java.awt.Point;导入 java.awt.RenderingHints;导入 java.awt.event.ActionEvent;导入 java.awt.event.ActionListener;导入 java.awt.event.MouseAdapter;导入 java.awt.event.MouseEvent;导入 java.awt.geom.AffineTransform;导入 java.awt.image.BufferedImage;导入 java.io.File;导入 java.io.IOException;导入 javax.imageio.ImageIO;导入 javax.swing.JFrame;导入 javax.swing.JPanel;导入 javax.swing.Timer;导入 javax.swing.UIManager;导入 javax.swing.UnsupportedLookAndFeelException;公共类 MoveTowards {公共静态无效主(字符串 [] args){新移动();}公共移动(){EventQueue.invokeLater(new Runnable() {@覆盖公共无效运行(){尝试 {UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {ex.printStackTrace();}JFrame frame = new JFrame("测试");frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);frame.add(new MoveTowardsPane());框架.pack();frame.setLocationRelativeTo(null);frame.setVisible(true);}});}类 MoveTowardsPane 扩展 JPanel {私有的最终 BufferedImage 图像;私有点 imagePosition = 新点(150, 150);私人点鼠标点;私有双 imageAngleRad = 0;公共 MoveTowardsPane() {缓冲图像 i = null;尝试 {i = ImageIO.read(getClass().getResource("/sprite.png"));} catch (IOException e) {e.printStackTrace();}图像=我;addMouseListener(新鼠标适配器(){@覆盖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);重绘();}});定时器 timer = new Timer(40, new ActionListener() {@覆盖public void actionPerformed(ActionEvent e) {如果(鼠标点!= null){int centerX = imagePosition.x + (image.getWidth()/2);int centerY = imagePosition.y + (image.getHeight()/2);如果(mousePoint.x != centerX){imagePosition.x += mousePoint.x <中心 X ?-1:1;}如果(mousePoint.y != centerY){imagePosition.y += mousePoint.y <中心Y ?-1:1;}重绘();}}});定时器开始();}@覆盖公共维度 getPreferredSize() {返回新维度(400, 400);}@覆盖受保护的无效paintComponent(图形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;仿射变换 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 不太适合这项任务,因为它需要考虑很多其他信息.此示例还将精灵转向"点击点,这是使用 JLabel 不容易实现的.

    原则上,移动组件的理论仍然相同.

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

    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

    解决方案

    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

    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

    这篇关于将图像移动到在 JFrame 上单击的光标位置的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆