【问题标题】:Moving an image with MouseListener when CLICKED单击时使用 MouseListener 移动图像
【发布时间】:2015-10-11 13:53:05
【问题描述】:

当用户单击/按住鼠标按钮时,我试图用鼠标移动图像。当用户按住鼠标时,我设法做到了这一点(它会用鼠标实时更新),但是,当我点击图像时,图像会将其位置调整到更新的区域,这不是我想要它做。如果图像被点击,我希望图像移动的唯一一次是用户再次点击,第二次。因此,假设用户单击位于 (0,0) 处的图像,如果用户再次单击屏幕上的其他位置,则该位置现在位于 (x,y)。

这是我所拥有的:

@Override
public void mouseClicked(MouseEvent e) {

    clickCount++;
    if(clickCount % 2 == 0){
        p.setLocation(e.getX(), e.getY());//p is just a panel that contains the img
        repaint();
    }
    System.out.println("mouse clicked...");

}

更新代码:

public void mouseClicked(MouseEvent e) {

    Object o = e.getSource();
    if(o instanceof JPanel)
        clickCount++;

    if(clickCount % 2 == 0 && clickCount != 0){
        p.setLocation(e.getX(), e.getY());
        repaint();
    }
    System.out.println("mouse clicked " + clickCount + " times");   
}

这更接近工作,但是,如果您单击屏幕上的任意位置(在 clickCount % 2 == 0 之后),则图像会移动。

【问题讨论】:

    标签: java swing mouseevent mouselistener


    【解决方案1】:

    mouseClicked被调用时,判断之前是否点击过某物,如果是,则将对象移动到当前位置,如果不是,检查用户点击的东西是否可移动并将其分配给变量(稍后用于检查)。

    移动对象后,将引用设置为null

    private JPanel clicked;
    
    @Override
    public void mouseClicked(MouseEvent e) {
    
        if (clicked != null) {
            clicked.setLocation(e.getX(), e.getY());
            clicked = null;
        } else {
            // Figure out if any panel was clicked and assign
            // a reference to clicked
        }
    
    }
    

    可运行示例...

    所以,听起来您正在尝试同时支持单击和拖动重定位,这有点......困难,因为两者所需的鼠标操作不同,因此您需要监控多个状态并做出决定例如,您可能处于的状态...

    import java.awt.Color;
    import java.awt.Component;
    import java.awt.Dimension;
    import java.awt.EventQueue;
    import java.awt.Point;
    import java.awt.event.MouseAdapter;
    import java.awt.event.MouseEvent;
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    import javax.swing.UIManager;
    import javax.swing.UnsupportedLookAndFeelException;
    
    public class MouseTest {
    
        public static void main(String[] args) {
            new MouseTest();
        }
    
        public MouseTest() {
            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 TestPane());
                    frame.pack();
                    frame.setLocationRelativeTo(null);
                    frame.setVisible(true);
                }
            });
        }
    
        public class TestPane extends JPanel {
    
            public TestPane() {
                setLayout(null);
                JPanel panel = new JPanel();
                panel.setBackground(Color.RED);
                panel.setSize(50, 50);
                panel.setLocation(50, 50);
                add(panel);
    
                MouseAdapter ma = new MouseAdapter() {
                    private Point offset;
                    private Point clickPoint;
                    private JPanel clickedPanel;
    
                    @Override
                    public void mousePressed(MouseEvent e) {
                        // Get the current clickPoint, this is used to determine if the
                        // mouseRelease event was part of a drag operation or not
                        clickPoint = e.getPoint();
                        // Determine if there is currently a selected panel or nor
                        if (clickedPanel != null) {
                            // Move the selected panel to a new location
                            moveSelectedPanelTo(e.getPoint());
                            // Reset all the other stuff we might other was have set eailer
                            offset = null;
                            clickedPanel = null;
                        } else {
                            // Other wise, find which component was clicked
                            findClickedComponent(e.getPoint());
                        }
                    }
    
                    @Override
                    public void mouseReleased(MouseEvent e) {
                        // Check to see if the current point is equal to the clickedPoint
                        // or not.  If it is, then this is part of a "clicked" operation
                        // meaning that the selected panel should remain "selected", otherwise
                        // it's part of drag operation and should be discarded
                        if (!e.getPoint().equals(clickPoint)) {
                            clickedPanel = null;
                        }
                        clickPoint = null;
                    }
    
                    @Override
                    public void mouseDragged(MouseEvent e) {
                        // Drag the selected component to a new location...
                        if (clickedPanel != null) {
                            moveSelectedPanelTo(e.getPoint());
                        }
                    }
    
                    protected void findClickedComponent(Point p) {
                        Component comp = getComponentAt(p);
                        if (comp instanceof JPanel && !comp.equals(TestPane.this)) {
                            clickedPanel = (JPanel) comp;
                            int x = p.x - clickedPanel.getLocation().x;
                            int y = p.y - clickedPanel.getLocation().y;
                            offset = new Point(x, y);
                        }
    
                    }
    
                    private void moveSelectedPanelTo(Point p) {
                        if (clickedPanel != null) {
                            int x = p.x - offset.x;
                            int y = p.y - offset.y;
                            System.out.println(x + "x" + y);
                            clickedPanel.setLocation(x, y);
                        }
                    }
    
                };
    
                addMouseListener(ma);
                addMouseMotionListener(ma);
            }
    
            @Override
            public Dimension getPreferredSize() {
                return new Dimension(200, 200);
            }
    
        }
    
    }
    

    【讨论】:

    • 对不起,你为什么要设置 clicked 为空?那你不是只能进入IF一次吗?
    • 一旦你移动了它,你就不想再继续移动了(我假设),所以下一次点击会选择其他面板被点击过。如果你想使用拖动,那么使用 MouseMotionListenermouseDragged 事件来代替
    • 非常感谢,这正是我想要的! :D
    • @mrnoobynoob 是的,这有点脑筋急转弯,但我很高兴它有所帮助
    • 如果您不介意,我还有最后一个问题,因为除非我了解所有内容,否则我不想使用它:为什么要在 findClickedComponent() 和 moveSelectedPanelTo() 中为 x 和 y 进行计算?我知道它会给你正确的、更新的坐标,但我似乎不明白为什么。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-15
    • 2017-08-25
    • 2016-06-10
    • 1970-01-01
    相关资源
    最近更新 更多