【问题标题】:How do I fire MouseMotionListener events in real-time?如何实时触发 MouseMotionListener 事件?
【发布时间】:2015-08-24 00:39:51
【问题描述】:

我正在尝试创建一个图形绘制程序,允许用户通过将鼠标拖到屏幕上来绘制红色像素。因此,在某种程度上,您可以将此程序视为 Microsoft 的 Paint 程序,但只有铅笔绘图工具和红色。

不幸的是,我的程序中的mouseDragged() 函数无法正常工作。如果我将鼠标移动得太快,它会跳过屏幕上的一些像素,如下所示:

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class FrameView extends JFrame {
    JPanel panel;
    Graphics2D drawingContext;

    public static void main(String[] args) {
        new FrameView();
    }

    public FrameView() {
        panel = new JPanel();
        panel.addMouseMotionListener(new MouseControls());
        panel.setBackground(Color.WHITE);
        this.add(panel);
        this.setSize(new Dimension(500, 500));
        this.setTitle("Drawing Program");
        this.setVisible(true);
        drawingContext = (Graphics2D)panel.getGraphics();
    }

    private class MouseControls extends MouseAdapter {
        @Override
        public void mouseDragged(MouseEvent e) {
            int x = e.getX();
            int y = e.getY();

            final int WIDTH = 1;
            final int HEIGHT = 1;
            Shape pixel = new Rectangle(x, y, WIDTH, HEIGHT);
            drawingContext.setColor(Color.RED);
            drawingContext.draw(pixel);
        }
    }
}

【问题讨论】:

  • You MouseListener 工作正常,这就是它的工作方式,它不会报告每个像素位置,而只是最可能的位置更新。相反,在点之间画线
  • 这不是自定义绘画在 Swing 中的工作方式,永远不要使用 getGraphics,它可以返回 null,并且当重新绘制组件时,您对它的任何绘画都可以被删除。请参阅 Painting in AWT and SwingPerforming Custom Painting 了解有关如何在 Swing 中进行绘画的更多详细信息

标签: java swing awt


【解决方案1】:

getGraphics 不是 Swing 中绘画的工作方式,相反,您应该覆盖组件的 paintComponent 方法并在那里执行您的自定义绘画。

绘制是破坏性的,预计每次调用paintComponent时,您将完全重新绘制组件的当前状态。

查看Painting in AWT and SwingPerforming Custom Painting 了解更多详情

至于你的“鼠标”问题,这实际上是它的工作原理,你不会被通知鼠标必须经过的每个像素位置,如果这样做,你的鼠标会在屏幕上严重滞后。相反,操作系统会根据用户输入的移动速度以不断增加的步长移动鼠标。

例如,不要只画点,而是在它们之间画线

nb:我特意把点画得更大,这样你就可以看到它们被报告的位置,你会看到所有的点(对于单次拖动)都是相连的

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.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Line2D;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class Test {

    public static void main(String[] args) {
        new Test();
    }

    public Test() {
        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<List<Point>> points = new ArrayList<>(25);
        private List<Point> activeList;

        public TestPane() {
            MouseAdapter ma = new MouseAdapter() {
                @Override
                public void mouseDragged(MouseEvent e) {

                    if (activeList != null) {
                        activeList.add(e.getPoint());
                        repaint();
                    }
                }

                @Override
                public void mousePressed(MouseEvent e) {
                    activeList = new ArrayList<>(25);
                    points.add(activeList);
                }

                @Override
                public void mouseReleased(MouseEvent e) {
                    if (activeList != null && activeList.isEmpty()) {
                        points.remove(activeList);
                    }
                    activeList = null;
                }

            };
            addMouseMotionListener(ma);
            addMouseListener(ma);
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(200, 200);
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g.create();
            g2d.setColor(Color.RED);
            for (List<Point> group : points) {
                Point previous = null;
                for (Point p : group) {
                    // You can get rid of this, it's simply to show
                    // where the points would actually be rendered
                    g2d.fill(new Ellipse2D.Float(p.x - 2, p.y - 2, 4, 4));
                    if (previous != null) {
                        g2d.draw(new Line2D.Float(previous, p));
                    }
                    previous = p;
                }
            }
            g2d.dispose();
        }

    }

}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-07-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-20
    • 1970-01-01
    • 1970-01-01
    • 2010-10-27
    相关资源
    最近更新 更多