Java 如何实时触发MouseMotionListener事件?
我正在尝试创建一个图形绘制程序,允许用户在屏幕上拖动鼠标来绘制红色像素。因此,在某种程度上,你可以把这个程序看作是微软的绘画程序,但是只有铅笔绘图工具和红色 不幸的是,我的程序中的Java 如何实时触发MouseMotionListener事件?,java,swing,awt,Java,Swing,Awt,我正在尝试创建一个图形绘制程序,允许用户在屏幕上拖动鼠标来绘制红色像素。因此,在某种程度上,你可以把这个程序看作是微软的绘画程序,但是只有铅笔绘图工具和红色 不幸的是,我的程序中的mouseDragged()函数工作不正常。如果我移动鼠标太快,它会跳过屏幕上的一些像素,如下所示: getGraphics不是如何在Swing中进行绘制,相反,您应该覆盖组件的paintComponent方法并在那里执行自定义绘制 绘制是破坏性的,当调用everpaintComponent时,您将完全重新绘制组件的
mouseDragged()
函数工作不正常。如果我移动鼠标太快,它会跳过屏幕上的一些像素,如下所示:
getGraphics
不是如何在Swing中进行绘制,相反,您应该覆盖组件的paintComponent
方法并在那里执行自定义绘制
绘制是破坏性的,当调用everpaintComponent
时,您将完全重新绘制组件的当前状态
查看和了解更多详细信息
至于你的“鼠标”问题,这实际上是它的工作原理,你不会被通知鼠标必须通过的每个像素位置,如果它通过了,你的鼠标会在屏幕上严重滞后。相反,操作系统会根据用户输入的移动速度以不断增加的步幅移动鼠标
例如,不要只画点,而是在它们之间画线
注意:我故意把点画得更大,这样你可以看到它们被报告的位置,你会看到所有的点(对于一次拖动)都是连接在一起的
导入java.awt.Color;
导入java.awt.Dimension;
导入java.awt.EventQueue;
导入java.awt.Graphics;
导入java.awt.Graphics2D;
导入java.awt.Point;
导入java.awt.event.MouseAdapter;
导入java.awt.event.MouseEvent;
导入java.awt.geom.Ellipse2D;
导入java.awt.geom.Line2D;
导入java.util.ArrayList;
导入java.util.List;
导入javax.swing.JFrame;
导入javax.swing.JPanel;
导入javax.swing.UIManager;
导入javax.swing.UnsupportedLookAndFeelException;
公开课考试{
公共静态void main(字符串[]args){
新测试();
}
公开考试(){
invokeLater(新的Runnable(){
@凌驾
公开募捐{
试一试{
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
}catch(ClassNotFoundException |实例化Exception | IllegalacessException |不支持ookandfeelException ex){
例如printStackTrace();
}
JFrame=新JFrame(“测试”);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(newtestpane());
frame.pack();
frame.setLocationRelativeTo(空);
frame.setVisible(true);
}
});
}
公共类TestPane扩展了JPanel{
私有列表点=新的ArrayList(25);
私有列表活动列表;
公共测试窗格(){
MouseAdapter ma=新的MouseAdapter(){
@凌驾
公共无效鼠标标记(鼠标事件e){
if(activeList!=null){
add(例如getPoint());
重新油漆();
}
}
@凌驾
公共无效鼠标按下(MouseEvent e){
activeList=newarraylist(25);
添加(活动列表);
}
@凌驾
公共无效MouseEvent(MouseEvent e){
if(activeList!=null&&activeList.isEmpty()){
删除(activeList);
}
activeList=null;
}
};
addMouseMotionListener(ma);
addMouseListener(硕士);
}
@凌驾
公共维度getPreferredSize(){
返回新维度(200200);
}
@凌驾
受保护组件(图形g){
超级组件(g);
Graphics2D g2d=(Graphics2D)g.create();
g2d.setColor(Color.RED);
对于(列表组:点){
上一点=空;
对于(p点:组){
//你可以摆脱它,它只是为了展示
//实际渲染点的位置
g2d.填充(新的椭圆E2D.浮动(p.x-2,p.y-2,4,4));
如果(上一个!=null){
g2d.draw(新的Line2D.Float(先前的,p));
}
先前=p;
}
}
g2d.dispose();
}
}
}
你的MouseListener
工作正常,这就是它的工作原理,它不会报告每个像素位置,只会报告最有可能的位置更新。相反,在点之间画线这不是自定义绘制在Swing中的工作方式,永远不要使用getGraphics
,它可以返回null
,并且在重新绘制组件时可以擦除绘制到它的任何内容。有关如何在Swing中进行绘制的更多详细信息,请参见和
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);
}
}
}
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();
}
}
}