Swing:如何减少 MouseInputAdapter 的响应时间? [英] Swing: How to reduce the response time of MouseInputAdapter?

查看:25
本文介绍了Swing:如何减少 MouseInputAdapter 的响应时间?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我制作了一个工具,可以让用户在屏幕截图上绘图.这是我的代码:

包 GUI.Views;导入 javax.swing.*;导入 javax.swing.event.MouseInputAdapter;导入 java.awt.*;导入 java.awt.event.MouseEvent;导入 java.awt.image.BufferedImage;公共类画布扩展 JPanel {公共静态整数半径 = 5;公共类 DrawPointListener 扩展 MouseInputAdapter{私人无效绘制(点p,整数半径){Graphics2D g2 = (Graphics2D)getGraphics();int x = (int)p.getX() - 半径/2;int y = (int)p.getY() - 半径/2;g2.fillOval(x, y, 半径, 半径);}@覆盖public void mousePressed(MouseEvent e) {draw(e.getPoint(), radius);}@覆盖public void mouseDragged(MouseEvent e) {draw(e.getPoint(), radius);}}私有 BufferedImage 屏幕截图;@覆盖公共无效paintComponent(图形g){super.paintComponent(g);Graphics2D g2 = (Graphics2D) g;g2.drawImage(this.screenShot, 0, 0, null);}公共画布(){this.setVisible(true);this.screenShot = getScreenShot();this.setCursor(新光标(Cursor.CROSSHAIR_CURSOR));DrawPointListener drawListener = new DrawPointListener();this.addMouseListener(drawListener);this.addMouseMotionListener(drawListener);}私有 BufferedImage getScreenShot() {尝试 {return new Robot().createScreenCapture(new Rectangle(Toolkit.getDefaultToolkit().getScreenSize()));} catch (AWTException e) {System.out.println("错误");返回空;}}公共静态无效主(字符串 [] args){JFrame f = new JFrame();Canvas canvas = new Canvas();f.setUndecorated(true);f.添加(画布);f.setExtendedState(JFrame.MAXIMIZED_BOTH);f.setVisible(true);}}

当您尝试在屏幕上缓慢绘制" 时,代码运行良好,但是当您快速移动鼠标时,您会看到这些点不连续,如下所示:

我认为是因为Listener有一个时间间隔.我该如何改进?

解决方案

您无法更改侦听器的时间间隔.您不能保证为每个像素生成一个事件.

因此,您需要在当前点和前一个点之间画一条线,而不是绘制单个点.

类似于:

import java.awt.*;导入 java.awt.event.MouseAdapter;导入 java.awt.event.MouseEvent;导入 java.util.ArrayList;导入 javax.swing.JFrame;导入 javax.swing.JPanel;类 DrawingPanel 扩展了 JPanel{私有 ArrayList>前一个 = 新的 ArrayList>();私有 ArrayList当前 = 新 ArrayList();私人 BasicStroke basicStroke;公共绘图面板(intstrokeSize){basicStroke = new BasicStroke(strokeSize, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND);MouseAdapter ma = new MouseAdapter(){@覆盖public void mousePressed(MouseEvent e){current.add( new Point(e.getX(), e.getY()) );}@覆盖public void mouseDragged(MouseEvent e){current.add( new Point(e.getX(), e.getY()) );重绘();}@覆盖public void mouseReleased(MouseEvent e){如果 (current.size() > 1){以前的.添加(当前);}当前 = 新 ArrayList();}};addMouseMotionListener( ma );addMouseListener( ma );}@覆盖protected void paintComponent(Graphics g){super.paintComponent(g);Graphics2D g2 = (Graphics2D) g;g2.setStroke( basicStroke );//绘制先前拖动的线条for (int i = 0; i 

points){for (int i = 0; i createAndShowGUI());/*EventQueue.invokeLater(new Runnable(){公共无效运行(){createAndShowGUI();}});*/}}

I've made a tool which could allow user to draw on screenshot.Here is my code:

package GUI.Views;

import javax.swing.*;
import javax.swing.event.MouseInputAdapter;
import java.awt.*;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;

public class Canvas extends JPanel {
    public static int radius = 5;
    public class DrawPointListener extends MouseInputAdapter{
        private void draw(Point p, int radius){
            Graphics2D g2 = (Graphics2D)getGraphics();
            int x = (int)p.getX() - radius/2;
            int y = (int)p.getY() - radius/2;
            g2.fillOval(x, y, radius, radius);
        }

        @Override
        public void mousePressed(MouseEvent e) {
            draw(e.getPoint(), radius);
        }

        @Override
        public void mouseDragged(MouseEvent e) {
            draw(e.getPoint(), radius);
        }
    }

    private BufferedImage screenShot;

    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2 = (Graphics2D) g;
        g2.drawImage(this.screenShot, 0, 0, null);
    }


    public Canvas() {
        this.setVisible(true);
        this.screenShot = getScreenShot();
        this.setCursor(new Cursor(Cursor.CROSSHAIR_CURSOR));

        DrawPointListener drawListener = new DrawPointListener();

        this.addMouseListener(drawListener);
        this.addMouseMotionListener(drawListener);
    }

    private BufferedImage getScreenShot() {
        try {
            return new Robot().createScreenCapture(new Rectangle(Toolkit.getDefaultToolkit().getScreenSize()));

        } catch (AWTException e) {
            System.out.println("Error");
            return null;
        }
    }

    public static void main(String[] args) {
        JFrame f = new JFrame();
        Canvas canvas = new Canvas();
        f.setUndecorated(true);
        f.add(canvas);
        f.setExtendedState(JFrame.MAXIMIZED_BOTH);
        f.setVisible(true);
    }
}

Code worked fine when you try to "draw" on the screen slowly, but when you move your mouse quickly, you would see those points are not consecutive, like this:

I think that because there is a time interval of Listener.How could I improve it?

解决方案

You can't change the time interval of the listener. You are NOT guaranteed to generate an event for every pixel.

So instead of drawing a single point, you need to draw a line between the current and previous point.

Something like:

import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;

import javax.swing.JFrame;
import javax.swing.JPanel;

class DrawingPanel extends JPanel
{
    private ArrayList<ArrayList<Point>> previous = new ArrayList<ArrayList<Point>>();
    private ArrayList<Point> current = new ArrayList<Point>();
    private BasicStroke basicStroke;

    public DrawingPanel(int strokeSize)
    {
        basicStroke = new BasicStroke(strokeSize, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND);

        MouseAdapter ma = new MouseAdapter()
        {
            @Override
            public void mousePressed(MouseEvent e)
            {
                current.add( new Point(e.getX(), e.getY()) );
            }

            @Override
            public void mouseDragged(MouseEvent e)
            {
                current.add( new Point(e.getX(), e.getY()) );
                repaint();
            }

            @Override
            public void mouseReleased(MouseEvent e)
            {
                if (current.size() > 1)
                {
                    previous.add( current );
                }

                current = new ArrayList<Point>();
            }
        };

        addMouseMotionListener( ma );
        addMouseListener( ma );
    }

    @Override
    protected void paintComponent(Graphics g)
    {
        super.paintComponent(g);

        Graphics2D g2 = (Graphics2D) g;
        g2.setStroke( basicStroke );

        //  Paint lines from previous drags

        for (int i = 0; i < previous.size(); i++)
        {
            drawLines(g, previous.get(i));
        }

        //  Paint line from current drag

        drawLines(g, current);
    }

    private void drawLines(Graphics g, ArrayList<Point> points)
    {
        for (int i = 0; i < points.size() - 1; i++)
        {
            int x = (int) points.get(i).getX();
            int y = (int) points.get(i).getY();
            int x2 = (int) points.get(i + 1).getX();
            int y2 = (int) points.get(i + 1).getY();
            g.drawLine(x, y, x2, y2);
        }
    }

    private static void createAndShowGUI()
    {
        JFrame frame = new JFrame("Drawing Panel");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(new DrawingPanel(15));
        frame.setSize(400, 400);
        frame.setLocationByPlatform( true );
        frame.setVisible( true );
    }

    public static void main(String[] args) throws Exception
    {
        EventQueue.invokeLater( () -> createAndShowGUI() );
/*
        EventQueue.invokeLater(new Runnable()
        {
            public void run()
            {
                createAndShowGUI();
            }
        });
*/
    }
}

这篇关于Swing:如何减少 MouseInputAdapter 的响应时间?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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