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

时间:2013-02-08 01:13:17

标签: java swing

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,然后在while为真时我将运行isDown循环。如果释放鼠标按钮,我会将isDown设置为false以终止while循环。

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

2 个答案:

答案 0 :(得分:7)

这是对事件调度线程的经典违反。

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

请查看Concurrency in Swing了解详情。

您真正应该做的是使用MouseMoitionListener来跟踪拖动事件。查看How to use Mouse Listeners了解详情。

drawingPanel.paint(drawingPanel.getGraphics(), (x - (x % 20) - 1), (y - (y % 20) - 1), 19, 19);也让我无所适从。

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

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

示例

enter image description here

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<Point, List<Point>> 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<Point>(25));
                }

                @Override
                public void mouseReleased(MouseEvent e) {
                    List<Point> points = mapPoints.get(currentPoint);
                    if (points.isEmpty()) {
                        mapPoints.remove(currentPoint);
                    }
                    currentPoint = null;
                }

                @Override
                public void mouseDragged(MouseEvent me) {
                    List<Point> 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<Point> points = mapPoints.get(startPoint);
                for (Point p : points) {
                    if (startPoint != null) {
                        g.drawLine(startPoint.x, startPoint.y, p.x, p.y);
                    }
                    startPoint = p;
                }
            }
        }
    }
}

答案 1 :(得分:2)

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

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

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

此解决方案的问题在于您的工作是在Swing组件上绘制。所有图形都应该以覆盖paintComponent方法完成。正如@MadProgrammer已经在解释你的那样,我不会详细介绍它。