0
votes

I'm using MouseMotion Listeners to add shapes to a HashSet, and then filling them in using Graphics2D. However when I move my mouse too fast the points no longer make a coherent line.

I've tried googling, but haven't found a relevant answer.

addMouseMotionListener(new MouseMotionAdapter() {
            public void mouseDragged(MouseEvent e) {
                //points.add(new Point(e.getX(), e.getY()));
                shapes.add(new ShapeInfo(circle, new Point(e.getX(), e.getY()), color));
                repaint();
            }
        });
for(ShapeInfo info : shapes) {
            Point location = info.point.getLocation();
            g2d.translate(location.x, location.y);
            g2d.setColor(info.color);
            g2d.fill(info.shape);
            g2d.translate(-location.x, -location.y);
        }

I hope to get a nice, smooth line made of circles, but end up with sacttered circles. https://imgur.com/a/KLOyPcn <- Here is what happends when I drag the mouse too fast while painting.

2
What do you mean by coherent line? And please include sufficent code to demonstrate the problem. - WJS

2 Answers

1
votes

Your mouse works at a certain frequency (normal mouse works around 100Hz) so it will pick a certain number of points while you move it.

If you cover 1000 px in half second (which is not really fast) it will pick 50 points, they will be spaced every 20 pixel.

If your circle has a radius of less than that you will see a dotted line.

Even using very a fast mouse could not lead you to have a continuous line.

You could draw a line between points instead of drawing a circle if you want, or interpolate coordinate between last circle and current one and create other circles in between the 2.

1
votes

Here try this.

import java.awt.*;
import java.awt.event.*;
import java.util.*;
import java.util.List;
import javax.swing.*;

public class FillOvals extends JPanel {
   private JFrame      frame  = new JFrame();
   private List<Point> points = new ArrayList<>();

   public static void main(String[] args) {
      SwingUtilities.invokeLater(() -> new FillOvals().start());
   }

   public FillOvals() {
      setPreferredSize(new Dimension(500, 500));
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.add(this);
      frame.pack();
      frame.setLocationRelativeTo(null); // center on screen
      frame.setVisible(true);
   }

   public void start() {
      MyMouseListener ml = new MyMouseListener();
      addMouseMotionListener(ml);
      addMouseListener(ml);
   }

   public void paintComponent(Graphics g) {
      super.paintComponent(g);
      if (points.size() < 1) {
         return;
      }
      Graphics2D g2d = (Graphics2D) g.create();

      // keep the line smooth on the edges
      g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
            RenderingHints.VALUE_ANTIALIAS_ON);

      g2d.setColor(Color.BLUE);
      Point p = points.get(0);
      int lastx = p.x;
      int lasty = p.y;
      g2d.setStroke(new BasicStroke(10.f));
      for (int i = 1; i < points.size(); i++) {

         p = points.get(i);
         g2d.drawLine(lastx, lasty, p.x, p.y);
         lastx = p.x;
         lasty = p.y;
      }
      g2d.dispose();
   }

   private class MyMouseListener extends MouseAdapter {

      public void mouseDragged(MouseEvent e) {
         points.add(e.getPoint());
         repaint();
      }

      public void mousePressed(MouseEvent e) {
         points.add(e.getPoint());
         repaint();
      }

   }
}

The JVM/mouse can't keep up with drawing circles that fast. The example I provided draws a line between two points on a continuous basis.