我怎么火实时的MouseMotionListener事件? [英] How do I fire MouseMotionListener events in real-time?

查看:197
本文介绍了我怎么火实时的MouseMotionListener事件?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想创建一个图形绘制程序,允许用户通过在其拖到自己的鼠标在屏幕上画出红色像素。因此,在某种程度上,你可以把这个方案作为微软的画图程序,但只有铅笔绘图工具和红色的。

不幸的是我在程序的的mouseDragged()功能不能正常工作。它会跳过一些像素的屏幕上,如果我移动鼠标太快了,像这样的:

在这里输入的形象描述

 进口java.awt中的*。
java.awt.event中导入*。
进口的javax.swing *。公共类FrameView扩展的JFrame {
    JPanel的面板;
    的Graphics2D的DrawingContext;    公共静态无效的主要(字串[] args){
        新FrameView();
    }    公共FrameView(){
        面板=新JPanel();
        panel.addMouseMotionListener(新MouseControls());
        panel.setBackground(Color.WHITE);
        this.add(面板);
        this.setSize(新尺寸(500,500));
        this.setTitle(绘图程序);
        this.setVisible(真);
        的DrawingContext =(Graphics2D的)panel.getGraphics();
    }    私有类MouseControls扩展MouseAdapter {
        @覆盖
        公共无效的mouseDragged(的MouseEvent E){
            INT X = e.getX();
            INT Y = e.getY();            最终诠释WIDTH = 1;
            最终诠释HEIGHT = 1;
            形状像素=新的Rectangle(X,Y,宽度,高度);
            drawingContext.setColor(Color.RED);
            drawingContext.draw(象素);
        }
    }
}


解决方案

的getGraphics 不是如何在Swing绘画作品,相反,你应该重写的paintComponent 组件的方法,并没有执行你的风俗画。

绘画是破坏性的,因此预计当过的paintComponent 被调用时,你将彻底重绘组件的当前状态。

看一看在AWT 绘画和Swing 和的Performing风俗画

至于你的鼠标的问题,这实际上是如何工作的,你就不会被通知每一个像素位置上的鼠标有穿过的,你的鼠标会落后可怕在屏幕上,如果它没有。相反,在OS移动鼠标在不断增加的基于用户输入的移动的速度的步骤。

除了绘制只是点,画出它们之间的直线,例如:

注:我故意画大点,所以你可以看到他们的报道在这里,你会看到,所有的点(对于单拖)连接

 进口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;公共类的测试{    公共静态无效的主要(字串[] args){
        新的测试();
    }    公开测试(){
        EventQueue.invokeLater(新的Runnable(){
            @覆盖
            公共无效的run(){
                尝试{
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                }赶上(ClassNotFoundException的| InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException前){
                    ex.printStackTrace();
                }                JFrame的帧=新的JFrame(测试);
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(新TestPane());
                frame.pack();
                frame.setLocationRelativeTo(NULL);
                frame.setVisible(真);
            }
        });
    }    公共类TestPane继承JPanel {        私人列表<名单,LT;点和GT;>点=新的ArrayList<>(25);
        私人列表<点和GT; activeList;        公共TestPane(){
            MouseAdapter MA =新MouseAdapter(){
                @覆盖
                公共无效的mouseDragged(的MouseEvent E){                    如果(activeList!= NULL){
                        activeList.add(e.getPoint());
                        重绘();
                    }
                }                @覆盖
                公共无效鼠标pressed(的MouseEvent E){
                    activeList =新的ArrayList<>(25);
                    points.add(activeList);
                }                @覆盖
                公共无效的mouseReleased(的MouseEvent E){
                    如果(activeList =空&放大器;!&放大器; activeList.isEmpty()){
                        points.remove(activeList);
                    }
                    activeList = NULL;
                }            };
            addMouseMotionListener(MA);
            addMouseListener将(MA);
        }        @覆盖
        公共尺寸的get preferredSize(){
            返回新尺寸(200,200);
        }        @覆盖
        保护无效paintComponent(图形G){
            super.paintComponent方法(G);
            Graphics2D的G2D =(Graphics2D的)g.create();
            g2d.setColor(Color.RED);
            对于(列表<点基团:分){
                点previous = NULL;
                为(P点:组){
                    //你可以摆脱这种,它只是展示
                    //其中点实际上将被呈现
                    g2d.fill(新Ellipse2D.Float(p.x - 2,p.y - 2,4,4));
                    如果(previous!= NULL){
                        g2d.draw(新Line2D.Float(previous页));
                    }
                    previous = P;
                }
            }
            g2d.dispose();
        }    }}

I am trying to create a graphics drawing program that allows the user to draw red pixels on the screen by dragging their mouse over it. So in a way, you can think of this program as Microsoft's Paint program but with only the pencil drawing tool and color red.

Unfortunately the mouseDragged() function in my program is not working properly. It will skip some of the pixels on the screen if I move my mouse too fast, like this:

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 is NOT how painting works in Swing, instead, you should be overriding the paintComponent method of the component and performing your custom painting there.

Painting is destructive, it is expected that when ever paintComponent is called, you will completely repaint the current state of the component.

Have a look at Painting in AWT and Swing and Performing Custom Painting for more details

As to you "mouse" problem, this is actually how it works, you won't be notified of EVERY pixel position the mouse has to pass through, your mouse would lag horribly across the screen if it did. Instead, the OS moves the mouse in ever increasing steps based on the speed of the movement of the user input.

Instead of drawing just the points, draw lines between them, for example

nb: I've deliberately painted the points larger so you can see where they are been reported, you will see that all the dots (for a single drag) are connected

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

    }

}

这篇关于我怎么火实时的MouseMotionListener事件?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆