gpt4 book ai didi

java - 如何实时触发 MouseMotionListener 事件?

转载 作者:行者123 更新时间:2023-12-03 01:24:26 27 4
gpt4 key购买 nike

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

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

enter image description here

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 时,您将完全重新绘制组件的当前状态。

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

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

例如,不要只绘制点,而是在点之间绘制线

Hello World

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();
}

}

}

关于java - 如何实时触发 MouseMotionListener 事件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32172993/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com