0

So, I have a map, that I want to be able to draw rectangles on to highlight an area. When the mouse is released a permanent rectangle is drawn on the map that persists until the mouse is dragged again to start the creation of a new rectangle. While the mouse is being dragged the rectangle outline should be created as it goes along.

The persisting rectangle is removed when the mouse is reclicked which given the application would mean that a new drag event would be started.

What happens is that the first rectangle is painted correctly and everything is fine, but subsequent rectangles that are currently being dragged have the corner cut off (image link at bottom).

If I click and then wait for the image to repaint before I start dragging then this problem does not exist, as well as if I sleep the thread before beginning to draw the rectangle in onMouseDragged so that it has time to repaint.

I'd like a more elegant solution than those to allow the screen to repaint before the rectangle created in onMouseDragged is shown on the screen. So what is the best way to get the repaint to complete without zapping part of the drawn rectangle?

Note that despite the look of the outline, the persisting rectangle that gets drawn is correct.

This is what the rectangle looks like the weird rectangle

public void onMousePressed(MapMouseEvent ev)
{       

    startPos = new Point(ev.getPoint());
    drawer.removeDrawings(pane.getMapContent());
    pane.repaint();
    pane.setIgnoreRepaint(true);        
}

public void onMouseDragged(MapMouseEvent ev)
{
    super.onMouseDragged(ev);
    if (enabled) {
        ensureGraphics();
        if (dragged)
        {
            // because we're in XOR mode, this has the effect of erases the previous rectangle
            graphics.drawRect(rect.x, rect.y, rect.width, rect.height);
        }
        else
        {


        }
        rect.setFrameFromDiagonal(startPos, ev.getPoint());
        graphics.drawRect(rect.x, rect.y, rect.width, rect.height);
        dragged = true;

    }
}
public void onMouseReleased(MapMouseEvent ev)
{
    super.onMouseReleased(ev);
    if (dragged) {
        ensureGraphics();
        dragged = false;           

        drawer drawable = new drawer();
        drawable.drawRectangle((Graphics2D) parentComponent.getGraphics().create(), rect.x, rect.y, rect.width, rect.height, pane.getMapContent());

        graphics.dispose();
        graphics = null;
        pane.setIgnoreRepaint(false);           
        pane.repaint();

    }
}
NolanPower
  • 409
  • 3
  • 11
  • For better help sooner, post an [SSCCE](http://sscce.org/). And also, what *is* your question? – Andrew Thompson Jul 12 '13 at 17:49
  • I'll try to work on a short compilable example. The actual question is how do I get the screen repaint to not mess with the rectangle being drawn without resorting to sleeps or explicitly demanding the user click and hold until the screen repaints. – NolanPower Jul 12 '13 at 17:53
  • When you go to edit your actual question into the question, don't forget to add an actual '?' at the end. ;) – Andrew Thompson Jul 12 '13 at 18:19

1 Answers1

1

You need to maintain a List<Rectangle> and add the current Rectangle to the list on mouseReleased(). GraphPanel illustrates the basic mouse handling. In your case, simply render the image, any existing rectangles and the current rectangle.

@Override
public void paintComponent(Graphics g) {
    super.paintComponent(g);
    // render background
    g.drawImage(image, 0, 0, this);
    // render existing rectangles
    for (Rectangle r : list) {
        r.draw(g);
    }
    // render the current dragged rectangle
    if (selecting) {
        g.setColor(Color.darkGray);
        g.drawRect(mouseRect.x, mouseRect.y,
            mouseRect.width, mouseRect.height);
    }
}

In the example, selecting is a boolean value that controls whether a new rectangle is beng drawn or an existing selection is being dragged to a new location.

As all rendering must occur on the EDT, I doubt that you need (or want) a new thread.

trashgod
  • 203,806
  • 29
  • 246
  • 1,045