1

In my app, I have a JPanel where I can paint. This is done by recording three points from the mouse clicked and mouse dragged events and then drawing a polyline between those three points. But if I use my tablet to draw, the lines aren't very smooth. The biggest problem I see is that if I quickly stroke my pen, the program won't even draw the line. If I go a bit slow, then it draws the line, but it lags behind so I can't see the line as it's being drawn. How can I make this smoother, like in one note where it will draw my lines no matter how fast I stroke my pen?

Here is the code I've been using, incase someone needs its

public class ScratchPad extends JPanel {

private Image image;
private Graphics2D graphics;
private ArrayList<Integer[]> coordinates = new ArrayList<>();

public ScratchPad() {

    setPreferredSize(new Dimension(1000, 500));
    addMouseListener(new MouseAdapter() {

        @Override
        public void mousePressed(MouseEvent me) {

            Integer[] coord = {me.getX(), me.getY()};
            coordinates.add(coord);
        }

        @Override
        public void mouseReleased(MouseEvent me) {
            coordinates.clear();
        }
    });
    addMouseMotionListener(new MouseMotionAdapter() {

        @Override
        public void mouseDragged(MouseEvent me) {

            Integer[] coord = {me.getX(), me.getY()};
            coordinates.add(coord);

            if (coordinates.size() >= 3) {
                if (graphics != null) {
                    drawLine();
                    repaint();
                }
            }
        }

    });

}

private void drawLine() {
    int[] x = {coordinates.get(0)[0], coordinates.get(1)[0], coordinates.get(2)[0]};
    int[] y = {coordinates.get(0)[1], coordinates.get(1)[1], coordinates.get(2)[1]};

    graphics.drawPolyline(x, y, 3);

    Integer[] temp = {coordinates.get(2)[0], coordinates.get(2)[1]};
    coordinates.clear();
    coordinates.add(temp);

}

@Override
protected void paintComponent(Graphics g) {
    if (image == null) {
        // image to draw null ==> we create
        image = createImage(getSize().width, getSize().height);
        graphics = (Graphics2D) image.getGraphics();
        // enable antialiasing
        graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        // clear draw area
        clear();
    }

    g.drawImage(image, 0, 0, null);
}

public void clear() {
    graphics.setPaint(Color.white);
    // draw white on entire draw area to clear
    graphics.fillRect(0, 0, getSize().width, getSize().height);
    graphics.setPaint(Color.black);
    repaint();
}

}

EDIT: Image added to show what's happening. Code for this image is taken MadProgrammer's second example in the comments below. The main issue here is that Java isn't detecting a portion of mouse drag. I drew the vertical line first, then from the top of vertical line, I started to draw the horizontal line. As you can see in the image, the horizontal line did not start immediately from the vertical line; it left a gap. This gap only shows up when I try to draw with my Wacom tablet, not with the mouse. This is the main issue I am trying to resolve at this point. I will be writing Japanese Kanji in this draw tool, which has small strokes that do not show up at all! I have to make them unnecessarily big so Java can draw them.

enter image description here

Aeleon
  • 169
  • 9
  • 1
    Record each of the points you can, then draw lines between the points. You'll want to set some rendering hints to improve the rendering – MadProgrammer Oct 25 '15 at 02:48
  • @MadProgrammer I am recording points, I store 3 points in an arraylist and then draw a polyline using those three points. Then I clear the arraylist and set the first point to the last point before the list was cleared. But it still doesn't draw the line if I stroke my pen really fast. If I were to take the time and record more points, then the line would lag even more behind my pen. – Aeleon Oct 25 '15 at 02:55
  • "if" what you want to do is "smooth" the line between a large distance of a point, you can either introduce more points that generate a curve or draw some kind of curved line, maybe using a `GeneralPath` of some kind – MadProgrammer Oct 25 '15 at 03:35
  • Remember that paintComponent must call `super.paintComponent(g)` before doing anything else. Your component may not get drawn correctly if you omit that. – VGR Oct 25 '15 at 03:41
  • @MadProgrammer I used linear interpolation to get two more points between the three points, the line looks a bit smoother. Still, it lags behind a bit and the doesn't draw if I move my pen a little too fast. If there is no other solution I might have to go and learn OpenGL or something. And I was so close to finishing this project. – Aeleon Oct 25 '15 at 04:10
  • Swing's double buffered by default, so introducing that second image seems a little overkill, however, if you're having performance issues, that's one to solve it, although `g.drawImage(image, 0, 0, null);` should probably be `g.drawImage(image, 0, 0, this);` – MadProgrammer Oct 25 '15 at 04:14
  • @MadProgrammer I got this code from the internet and then modified it, I can't see where the second image is. Changed null to this. The problem still exists. I took a closer look and it seems that there is lag right when I start to draw. The program should start drawing as soon as I click, but when I go really slowly, I can see that the cursor has to move about a mm or so before the line starts to get drawn. It is noticeable and I think is causing the lag. I should point out that this lag doesn't occur if I draw with the mouse. The program starts drawing the line immediately after I click. – Aeleon Oct 25 '15 at 04:29
  • Every OS will have a threshold of movement before it starts a drag operation, they may not be anything your can do about that – MadProgrammer Oct 25 '15 at 04:31
  • @MadProgrammer I don't think its the OS's fault. My pen works fine in onenote and MS paint, and even my program work fine with a mouse. I think that Java doesn't like pens. I'll see if OpenGL can do better but I'll to spend time learning that first. This just plain sucks. Thanks for trying to help though, I appreciate it you being patient with me. – Aeleon Oct 25 '15 at 04:38
  • The try using something more like [this example](http://stackoverflow.com/questions/14764157/mouseevent-is-not-registering-a-release-when-i-release-the-mouse-button/14764264#14764264) – MadProgrammer Oct 25 '15 at 04:52
  • Or [this example](http://stackoverflow.com/questions/32172993/how-do-i-fire-mousemotionlistener-events-in-real-time/32173243#32173243) – MadProgrammer Oct 25 '15 at 04:58
  • @MadProgrammer This is really interesting, in both the programs, my Netbeans is throwing errors at the mouse event overrides and the getPoint() methods, which exists in the [documentation](https://docs.oracle.com/javase/7/docs/api/java/awt/event/MouseEvent.html#getPoint()). But I managed to fix that in the second one by replacing getPoint() with getX() and getY(). What I am having trouble with is the line g2d.draw(new Line2D.Float(previous, p)); where I am getting a 'can't convert point to point2D' error which I can't seem to fix – Aeleon Oct 25 '15 at 06:09
  • That's interesting, I've dumped both into Netbeans without an issue. Make sure you've imported `java.awt.Point` – MadProgrammer Oct 25 '15 at 06:12
  • @MadProgrammer copy pasted it again and it fixed it for some reason. Must have messed up the first time. You second app is showing me that java doesn't register the first mm or so of mouse drag if it is coming from my pen. Works fine if I try to draw with my mouse. I attached an image of what's happening with the pen in my post above. I draw the vertical line first, then I draw the horizontal line starting on the end of the vertical line. – Aeleon Oct 25 '15 at 06:29
  • Could add the comment to the question, about Java not detecting that first portion of the drag and highlight it, this seems to be the particular issue that needs to be resolved – MadProgrammer Oct 25 '15 at 06:31
  • @MadProgrammer I edited my post, hopefully that is enough detail. I'm going to bed now, I'll deal with the rest tomorrow. – Aeleon Oct 25 '15 at 06:39

1 Answers1

0

If your using a wacom pen is it reasonably fast in other apps?, If not there are some fixes to try:

https://boutiqueretouching.com/fix-wacom-lag/

A) Wacom preferences app -> mapping -> use windows ink (off)

B) search -> flicks -> turn flicks on and off -> uncheck use flicks

C) go to windows settings –> devices –> pen / “pen and touch settings -> Switch off “show visual effects” and “show cursor.”

andrew pate
  • 3,833
  • 36
  • 28