如何在没有取消选择的情况下单击并拖动某些内容

该程序是一个动画,可以在屏幕上创建汽车和/或卡车图标。 我现在的方式是它无法正常工作。 具体来说,程序没有单击并向右拖动。 如果未选择一个对象,则一旦单击该对象,将显示更大胆以显示它已被选中。 从那里我们希望能够拖动它,程序将重绘鼠标所在的任何地方。 如果图像未被选中,当我点击并拖动它时,它可以正常工作。 我遇到的问题是图像是否已被选中。 如果已经选择了图像,当我将鼠标移动到它并单击它以将其移动到不同的位置而不是移动时,它会被取消选择,因此不会发生移动。 以下是mousePressed和mouseDragged事件的代码。 我认为这就是问题所在,但我不确定是什么导致了这个问题。

addMouseListener(new MouseAdapter() { public void mousePressed(MouseEvent event) { mousePoint = event.getPoint(); for (SceneShape s : shapes) { if (s.contains(mousePoint)) s.setSelected(!s.isSelected()); } repaint(); } }); addMouseMotionListener(new MouseMotionAdapter() { public void mouseDragged(MouseEvent event) { Point lastMousePoint = mousePoint; mousePoint = event.getPoint(); for (SceneShape s : shapes) { if (s.isSelected()) { double dx = mousePoint.getX() - lastMousePoint.getX(); double dy = mousePoint.getY() - lastMousePoint.getY(); s.translate((int) dx, (int) dy); } } repaint(); } }); 

有人可以帮我解释当我拖动它而不是移动它以及如何解决这个问题时,程序取消选择已经选择的图像是什么原因? 谢谢。

拖动操作的一个副作用是不会调用mouseClicked 。 为什么这很重要? 基本上,您可以使用此事实来决定是否应在mouseClicked事件中取消选择对象,而不是像mousePressedmouseReleased

它确实需要您维护有关当前和以前状态的一些信息,因此您知道该对象是刚刚被选中还是之前被选中,但基本思想很有效。

拉我一把

 import java.awt.Color; import java.awt.Dimension; import java.awt.EventQueue; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Point; import java.awt.Rectangle; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.util.ArrayList; import java.util.Collections; import java.util.List; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.UIManager; import javax.swing.UnsupportedLookAndFeelException; public class WhatADrag { public static void main(String[] args) { new WhatADrag(); } public WhatADrag() { 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 { private List boxes; private Rectangle selected; public TestPane() { boxes = new ArrayList<>(25); int x = 0; int y = 0; for (int index = 0; index < 10; index++) { boxes.add(new Rectangle(x, y, 100, 100)); x += 25; y += 25; } MouseAdapter ma = new MouseAdapter() { private Rectangle previous; private Point delta; @Override public void mousePressed(MouseEvent e) { List reversed = new ArrayList<>(boxes); Collections.reverse(reversed); previous = selected; if (selected == null || !selected.contains(e.getPoint())) { for (Rectangle box : reversed) { if (box.contains(e.getPoint())) { selected = box; delta = new Point(e.getX() - selected.x, e.getY() - selected.y); repaint(); break; } } if (selected != null) { boxes.remove(selected); boxes.add(boxes.size() - 1, selected); } } else if (selected != null) { delta = new Point(e.getX() - selected.x, e.getY() - selected.y); } } @Override public void mouseClicked(MouseEvent e) { if (selected == previous && selected != null && selected.contains(e.getPoint())) { selected = null; repaint(); } } @Override public void mouseDragged(MouseEvent e) { if (selected != null) { int x = e.getX() - delta.x; int y = e.getY() - delta.y; selected.x = x; selected.y = y; repaint(); } } }; addMouseListener(ma); addMouseMotionListener(ma); } @Override public Dimension getPreferredSize() { return new Dimension(400, 400); } protected void paintComponent(Graphics g) { super.paintComponent(g); Graphics2D g2d = (Graphics2D) g.create(); for (Rectangle box : boxes) { if (box != selected) { g2d.setColor(Color.BLUE); g2d.fill(box); g2d.setColor(Color.BLACK); g2d.draw(box); } } if (selected != null) { g2d.setColor(Color.CYAN); g2d.fill(selected); g2d.setColor(Color.BLUE); g2d.draw(selected); } g2d.dispose(); } } } 

我迷失了。 我正在查看所有这些代码,甚至不了解它在做什么。

是的,我觉得我的代码很多。

基本上…

第一个: mousePressed ,我反转我的对象列表,因为最顶层的组件将是列表中的最后一个(这是我的要求),我将当前选中的对象存储在上previous变量中,我用它来确定是否存在一直是选择的变化。 我检查用户是否点击了selected对象,如果他们这样做了,我们基本上可以跳过其他所有内容。 如果没有,我们确定他们点击了什么,如果有的话。 delta只是它们单击的位置和对象的位置之间的差异,这用于使拖动更自然

如果没有发生拖动:调用mouseClicked 。 我们测试以查看selected对象是否等于previous对象,如果在selected对象中单击鼠标,如果这些为true ,则应取消选择当前selected对象。 否则用户基本上只是更改了选择,因此我们不希望立即取消选择它。

否则,如果发生拖动: mouseDragged 。 我们只是检查是否selected某些东西,我们计算当前鼠标位置和“点击偏移量”之间的差异并更新selected对象的位置

清除泥浆:P

还有一点要记住, mouseReleased将始终在mousePressed之后mousePressed ,即使mouseClicked不是(在没有拖动时mouseReleased之后调用)。