I'm new to Java2D (but not to Swing) so be gentle.  :-)

Mostly for my own education I'm building an image panel component.

One of its features is that you can drag a semi-transparent over the rendered 
image (which might be scaled).  Eventually I plan to hook this up to some 
cropping functionality, but right now I'm just working with the drawing calls.

I have this working so that drawing rectangles does indeed do exactly what I 
want.  The problem is that the rectangle flickers.

The approach I've taken is, within my mouse listeners, to erase the prior 
rectangle before drawing the new one by calling paintImmediately with the 
rectangle's coordinates.  Indeed, this does exactly what I want--that portion 
of the image that was dirtied by the prior rectangle repaints.  But in my 
paintComponent() method, it looks like I have to draw the entire image, where 
I'd prefer just to redraw the dirty part.  I have to do this because in order 
to determine what rectangle in the image is actually dirty, I have to scale it 
again.

I've attached the code for my (functional, working) image panel class below.  
Could someone kindly investigate the paintComponent() override--particularly 
the graphics.drawImage() call?  Can you think of a more efficient way to do 
this to reduce the flickering?

Thanks,
Laird

[code]
package bricks.swing.imagepanel;

import java.awt.*; // imports starred to reduce space
import java.awt.event.*;
import javax.swing.*;

public class ImagePanel extends JPanel {

  private Image suppliedImage;
  private Image imageToPaint;
  private final MouseAdapter mouseListener;
  private boolean erasing;
  private int lastX;  
  private int lastY;

  public ImagePanel() {
    super();
    this.lastX = -1;
    this.lastY = -1;
    this.mouseListener = new MouseAdapter() {
        private int startX;
        private int startY;
        private boolean dragging;
        private Graphics g;

        @Override
        public final void mousePressed(final MouseEvent event) {
          assert event != null;
          if (!this.dragging) {
            this.dragging = true;
            this.g = ImagePanel.this.getGraphics();
            assert this.g != null;
            this.g.setColor(new Color(0, 0, 255, 30));
            if (ImagePanel.this.lastX >= 0) {
              assert ImagePanel.this.lastY >= 0;
              // That means that someone drew a band on here before, so wipe it
              // out.
              this.drawRubberBand(true); // true == erase
            }
            this.startX = event.getX();
            this.startY = event.getY();
            ImagePanel.this.lastX = this.startX;
            ImagePanel.this.lastY = this.startY;
            this.drawRubberBand(false); // false == draw, not erase
          }
        }

        @Override
        public final void mouseReleased(final MouseEvent event) {
          assert event != null;
          if (this.dragging) {
            this.dragging = false;
            this.drawRubberBand(true); // true == erase
            this.drawRubberBand(false); // false == draw
            assert this.g != null;
            this.g.dispose();
          }
        }

        @Override
        public final void mouseDragged(final MouseEvent event) {
          assert event != null;
          if (this.dragging) {
            this.drawRubberBand(true);
            ImagePanel.this.lastX = event.getX();
            ImagePanel.this.lastY = event.getY();
            this.drawRubberBand(false);
          }
        }

        private final void drawRubberBand(final boolean erase) {
          assert this.g != null;
          
          final int x;
          final int width;
          if (ImagePanel.this.lastX > this.startX) {
            x = this.startX;
            width = ImagePanel.this.lastX - this.startX;
          } else {
            x = ImagePanel.this.lastX;
            width = this.startX - ImagePanel.this.lastX;
          }

          final int y;
          final int height;
          if (ImagePanel.this.lastY > this.startY) {
            y = this.startY;
            height = ImagePanel.this.lastY - this.startY;
          } else {
            y = ImagePanel.this.lastY;
            height = this.startY - ImagePanel.this.lastY;
          }

          if (erase) {
            ImagePanel.this.erasing = true;
            ImagePanel.this.paintImmediately(x, y, width, height);
            ImagePanel.this.erasing = false;
          } else {
            this.g.fillRect(x, y, width, height);
          }

        }
      };
    this.addMouseListener(this.mouseListener);
    this.addMouseMotionListener(this.mouseListener);
  }

  public Image getImage() {
    return this.suppliedImage;
  }

  public void setImage(final Image image) {
    final Image old = this.getImage();
    this.suppliedImage = image;
    this.imageToPaint = image;
    if (image != null) {
      final int height = image.getHeight(this);
      final int width = image.getWidth(this);
      if (height >= 0 && width >= 0) {
        this.setPreferredSize(new Dimension(height, width));
      }
    }
    this.firePropertyChange("image", old, this.getImage());
  }

  @Override
  protected void paintComponent(final Graphics graphics) {
    super.paintComponent(graphics);
    if (!this.erasing) {
      this.lastX = -1;
      this.lastY = -1;
    }
    if (graphics != null) {
      // Could this be an issue?  The graphics clip is probably set to a tiny 
fraction of
      // the overall image size.  I'd really like to only drawImage() on that 
part.  But
      // I could be scaling the image, so I don't really know where that 
portion of the 
      // *scaled* image is.  So I have to tell the graphics to draw the whole 
image,
      // it, and then apply the clip (which is basically what 
paintImmediately(Rectangle)
      // is doing when it calls through to here).  Is there a better way?
      graphics.drawImage(this.imageToPaint, 0, 0, this.getWidth(), 
this.getHeight(), this);
    }
  }

}
[/code]
[Message sent by forum member 'ljnelson' (ljnelson)]

http://forums.java.net/jive/thread.jspa?messageID=294019

===========================================================================
To unsubscribe, send email to [EMAIL PROTECTED] and include in the body
of the message "signoff JAVA2D-INTEREST".  For general help, send email to
[EMAIL PROTECTED] and include in the body of the message "help".

Reply via email to