如何实时触发MouseMotionListener事件?

我正在尝试创建一个图形绘制程序,允许用户通过将鼠标拖到屏幕上来绘制红色像素。 所以在某种程度上,您可以将此程序视为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); } } } 

getGraphics不是绘画在Swing中的工作原理,相反,你应该重写组件的paintComponent方法并在那里执行自定义绘制。

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

有关更多详细信息,请参阅AWT和Swing中的 绘画以及执行自定义绘画

至于你的“鼠标”问题,实际上它是如何工作的,你不会被告知鼠标必须经过的每个像素位置,如果它的话,你的鼠标会在屏幕上可怕地滞后。 相反,OS基于用户输入的移动速度以不断增加的步长移动鼠标。

例如,不是仅绘制点,而是在它们之间绘制线条

你好,世界

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> points = new ArrayList<>(25); private List 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 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(px - 2, py - 2, 4, 4)); if (previous != null) { g2d.draw(new Line2D.Float(previous, p)); } previous = p; } } g2d.dispose(); } } }