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".