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

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

4

2 回答 2

7

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

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

查看Swing 中的并发以获取更多详细信息。

您真正应该做的是使用 aMouseMoitionListener来跟踪拖动事件。查看如何使用鼠标侦听器了解更多详细信息。

drawingPanel.paint(drawingPanel.getGraphics(), (x - (x % 20) - 1), (y - (y % 20) - 1), 19, 19);也让我担心不已。

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

您应该创建一个自定义组件(例如 a 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<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;
                }
            }
        }
    }
}
于 2013-02-08T01:24:46.563 回答
2

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

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

一种典型的解决方案是启动一个新线程来完成长时间运行的工作。它将释放事件调度线程,并且将调用您的 mouseReleased() 侦听器。

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

于 2013-02-08T01:23:55.000 回答