GraphicsPane extends JComponent
@Override
protected void paintComponent(Graphics g) {
// honor the opaque property
if (isOpaque()) {
g.setColor(getBackground());
g.fillRect(0, 0, getWidth(), getHeight());
}
}
DefaultView2d<E extends ImageElement> extends GraphicsPane
/** paint routine */
@Override
public synchronized void paintComponent(Graphics g) {
if (g instanceof Graphics2D) {
draw((Graphics2D) g);
}
}
protected void draw(Graphics2D g2d) {
Stroke oldStroke = g2d.getStroke();
Paint oldColor = g2d.getPaint();
double viewScale = getViewModel().getViewScale();
double offsetX = getViewModel().getModelOffsetX() * viewScale;
double offsetY = getViewModel().getModelOffsetY() * viewScale;
// Paint the visible area
g2d.translate(-offsetX, -offsetY);
// Set font size for computing shared text areas that need to be repainted in different zoom magnitudes.
Font defaultFont = getFont();
g2d.setFont(defaultFont);
imageLayer.drawImage(g2d);
drawLayers(g2d, affineTransform, inverseTransform);
g2d.translate(offsetX, offsetY);
drawPointer(g2d);
if (infoLayer != null) {
g2d.setFont(getLayerFont());
infoLayer.paint(g2d);
}
g2d.setFont(defaultFont);
g2d.setPaint(oldColor);
g2d.setStroke(oldStroke);
}
@Override
public void drawLayers(Graphics2D g2d, AffineTransform transform, AffineTransform inverseTransform) {
if ((Boolean) actionsInView.get(ActionW.DRAW.cmd())) {
getLayerModel().draw(
g2d,
transform,
inverseTransform,
new Rectangle2D.Double(modelToViewLength(getViewModel().getModelOffsetX()),
modelToViewLength(getViewModel().getModelOffsetY()), getWidth(), getHeight()));
}
}
下面分两条绘制主线,一条绘制图形,一条绘制图像
RenderedImageLayer<E extends ImageElement> implements Layer
public void drawImage(Graphics2D g2d) {
// Get the clipping rectangle
if (!visible || displayImage == null) {
return;
}
// Rectangle clipBounds = g2d.getClipBounds();
// if (clipBounds == null || clipBounds.isEmpty()) {
// clipBounds =
// new Rectangle(displayImage.getMinX(), displayImage.getMinY(), displayImage.getWidth(),
// displayImage.getHeight());
// g2d.setClip(clipBounds);
// }
Shape clip = g2d.getClip();
if (clip instanceof Rectangle2D) {
Rectangle2D rect =
new Rectangle2D.Double(displayImage.getMinX(), displayImage.getMinY(), displayImage.getWidth() - 1,
displayImage.getHeight() - 1);
rect = rect.createIntersection((Rectangle2D) clip);
if (rect.isEmpty()) {
return;
}
g2d.setClip(rect);
}
try {
g2d.drawRenderedImage(displayImage, AffineTransform.getTranslateInstance(0, 0));
} catch (OutOfMemoryError e1) {
System.gc();
try {
Thread.sleep(100);
} catch (InterruptedException et) {
}
}
g2d.setClip(clip);
}
class AbstractLayerModel implements LayerModel
@Override
public void draw(Graphics2D g2d, AffineTransform transform, AffineTransform inverseTransform, Rectangle2D viewClip) {
Rectangle2D bound = null;
// Get the visible view in real coordinates, note only Sun g2d return consistent clip area with offset
Shape area = inverseTransform.createTransformedShape(viewClip == null ? g2d.getClipBounds() : viewClip);
bound = area.getBounds2D();
g2d.translate(0.5, 0.5);
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, antialiasingOn);
// g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, alpha));
for (int i = 0; i < layers.size(); i++) {
AbstractLayer layer = layers.get(i);
if (layer.isVisible()) {
layer.paint(g2d, transform, inverseTransform, bound);
}
}
// g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1.0f));
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, antialiasingOff);
g2d.translate(-0.5, -0.5);
}
DragLayer extends AbstractLayer
@Override
public void paint(Graphics2D g2d, AffineTransform transform, AffineTransform inverseTransform, Rectangle2D bounds) {
if (graphics == null)
return;
for (Graphic graphic : graphics) {
if (bounds != null) {
Rectangle repaintBounds = graphic.getRepaintBounds(transform);
if (repaintBounds != null && repaintBounds.intersects(bounds)) {
graphic.paint(g2d, transform);
} else {
GraphicLabel graphicLabel = graphic.getGraphicLabel();
Rectangle2D labelBounds = (graphicLabel != null) ? graphicLabel.getBounds(transform) : null;
if (labelBounds != null && labelBounds.intersects(bounds)) {
graphic.paintLabel(g2d, transform);
// TODO would be simpler to integrate intersect check inside graphic instance
}
}
} else {
// convention is when bounds equals null graphic is repaint
graphic.paint(g2d, transform);
graphic.paintLabel(g2d, transform);
}
}
}