views:

277

answers:

1

I'm working with an application in which I add a heavyweight (Canvas) to a JFrame. The Canvas is a 3rd party component, so I am required to keep it heavyweight. I'd like to add capabilities for the user to draw on the canvas and paint a selection rectangle.

I don't think I can do this with the glass pane since the heavyweight canvas will be displayed over the glass pane. I've tried adding a mouse listener to the canvas and drawing directly on its graphics, but that seems to give the "flicker" effect since it's not a lightweight double-buffered component.

Is there a way to achieve this smooth drawing on heavyweight components?

This is my current attempt in the paint method of the heavyweight component, but there is still the flashing.

    @Override
    public void paint(Graphics g)
    {
        super.paint(g);
        if (showUserSelection)
        {
            Point startDrawPoint = new Point(Math.min(startSelectPoint.x,
                    endSelectPoint.x), Math.min(startSelectPoint.y,
                    endSelectPoint.y));
            Point endDrawPoint = new Point(Math.max(startSelectPoint.x,
                    endSelectPoint.x), Math.max(startSelectPoint.y,
                    endSelectPoint.y));
            int w = endDrawPoint.x - startDrawPoint.x;
            int h = endDrawPoint.y - startDrawPoint.y;
            if (w > 0 && h > 0)
            {
                BufferedImage img = new BufferedImage(w, h,
                        BufferedImage.TYPE_INT_ARGB);
                Graphics2D imgGraphics = img.createGraphics();
                imgGraphics.fillRect(0, 0, w, h);
                g.drawImage(img, startDrawPoint.x, startDrawPoint.y, w, h,
                        null);

            }
        }
    }

thanks,

Jeff

+2  A: 

I'm not aware of a drop in "Host AWT/SWT in Swing" component, but you should be able to build a work around yourself.

Have you considered implementing double buffering yourself?

You're 90% of the way there with your code, just at a glance.

@Override
public void paint(Graphics g)
{
    BufferedImage buffer = new BufferedImage(COMPONENT_WIDTH, COMPONENT_HEIGHT, BufferedImage.TYPE_INT_ARGB);

    Graphics bufferG = buffer.getGraphics();

    super.paint(bufferG);
    if (showUserSelection)
    {
        Point startDrawPoint = new Point(Math.min(startSelectPoint.x,
                endSelectPoint.x), Math.min(startSelectPoint.y,
                endSelectPoint.y));
        Point endDrawPoint = new Point(Math.max(startSelectPoint.x,
                endSelectPoint.x), Math.max(startSelectPoint.y,
                endSelectPoint.y));
        int w = endDrawPoint.x - startDrawPoint.x;
        int h = endDrawPoint.y - startDrawPoint.y;
        if (w > 0 && h > 0)
        {
            bufferG.fillRect(startDrawPoint.x, startDrawPoint.y, w, h);

        }
    }

    g.drawImage(buffer, 0, 0, null);
}
Kevin Montrose
thanks. appreciate the help. i thought i was just slightly off, and i think this is getting me closer.
Jeff Storey