当我释放鼠标按钮时,MouseEvent没有注册版本

public void mousePressed(MouseEvent e) { //Invoked when a mouse button has been pressed on a component. if (e.getButton() == MouseEvent.BUTTON1) { isDown = true; System.out.println("isDown is now true"); } if (e.getButton() == MouseEvent.BUTTON3) { isDown2 = true; System.out.println("isDown2 is now true"); } do { Point location = MouseInfo.getPointerInfo().getLocation(); int x = location.x - (drawingPanel.getLocationOnScreen()).x; int y = location.y - (drawingPanel.getLocationOnScreen()).y; drawingPanel.paint(drawingPanel.getGraphics(), (x - (x % 20) - 1), (y - (y % 20) - 1), 19, 19); } while (isDown); System.out.println("Mouse has been pressed down."); } public void mouseReleased(MouseEvent e) { //Invoked when a mouse button has been released on a component. if (e.getButton() == MouseEvent.BUTTON1) { isDown = false; System.out.println("isDown is now false"); } if (e.getButton() == MouseEvent.BUTTON3) { isDown2 = false; System.out.println("isDown2 is now false"); } System.out.println("Mouse has been released."); } 

这就是我到目前为止所拥有的。 我最初的意图是设计代码,以便在按下鼠标时将布尔值isDown设置为true,然后在isDown为true while运行while循环。 如果释放鼠标按钮,我会将isDown设置为false以终止while循环。

我搞砸了什么? 两个MouseEvent方法不可能同时运行吗? isDown布尔变量的更改没有被注册,我的手上有一个无限的while循环。

这是对Event Dispatching Thread的经典违反。

所有UI代码都在单个线程中运行。 所有事件都从同一个线程调度UI,这意味着如果您阻止此线程(使用循环或其他阻塞操作),则不会调度任何事件。 这将使您的程序看起来像挂起。

有关更多详细信息,请参阅Swing中的Concurrency 。

你真正应该做的是使用MouseMoitionListener来跟踪拖动事件。 有关更多详细信息,请查看如何使用鼠标侦听器 。

drawingPanel.paint(drawingPanel.getGraphics(), (x - (x % 20) - 1), (y - (y % 20) - 1), 19, 19); 也让我担心永无止境。

你永远不应该使用getGraphics来执行自定义绘画。 getGraphics可以返回null,只是最后一个绘制周期的快照。 使用此方法完成的任何绘制将在发生另一次重绘时被删除/清除。

您应该创建一个自定义组件(例如JPanel )并覆盖它的paintComponent方法并执行其中所需的任何绘制。 查看执行自定义绘画了解更多详情

在此处输入图像描述

 public class MouseDraggedTest { public static void main(String[] args) { new MouseDraggedTest(); } public MouseDraggedTest() { EventQueue.invokeLater(new Runnable() { @Override public void run() { try { UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); } catch (Exception ex) { } JFrame frame = new JFrame("Test"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.add(new TestPane()); frame.pack(); frame.setLocationRelativeTo(null); frame.setVisible(true); } }); } public class TestPane extends JPanel { private Map> mapPoints; private Point currentPoint; public TestPane() { mapPoints = new HashMap<>(25); MouseAdapter mouseListener = new MouseAdapter() { @Override public void mousePressed(MouseEvent e) { currentPoint = e.getPoint(); mapPoints.put(currentPoint, new ArrayList(25)); } @Override public void mouseReleased(MouseEvent e) { List points = mapPoints.get(currentPoint); if (points.isEmpty()) { mapPoints.remove(currentPoint); } currentPoint = null; } @Override public void mouseDragged(MouseEvent me) { List points = mapPoints.get(currentPoint); points.add(me.getPoint()); repaint(); } }; addMouseListener(mouseListener); addMouseMotionListener(mouseListener); } @Override public Dimension getPreferredSize() { return new Dimension(200, 200); } @Override protected void paintComponent(Graphics g) { super.paintComponent(g); for (Point startPoint : mapPoints.keySet()) { List points = mapPoints.get(startPoint); for (Point p : points) { if (startPoint != null) { g.drawLine(startPoint.x, startPoint.y, px, py); } startPoint = p; } } } } } 

你正在mousePressed()方法中执行while循环。 这意味着你正在阻止Swing Event Dispatch Thread! 由于只要isDown为true,此方法就不会返回,因此执行将不会返回到侦听器处理程序,该处理程序将永远不会调用mouseReleased()侦听器。

作为一般规则,您永远不应在侦听器中启动长时间运行的操作,因为只要它运行,您的GUI就不会响应任何事件。 在这种情况下,这意味着永远! 任何监听器都不应该只设置几个标志,然后返回。 您的应用程序必须保持响应。

一个典型的解决方案是启动一个新线程来执行长时间运行的工作。 它将释放Event Dispatching Thread并调用mouseReleased()侦听器。

此解决方案的问题在于您的工作是在Swing组件上绘制。 所有图形都应该在重写的paintComponent方法中完成。 由于@MadProgrammer已在向您解释,我不会详细介绍它。