Swing:如何减少 MouseInputAdapter 的响应时间? [英] Swing: How to reduce the response time of 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屋!