目前我正在使用一个应用程序,该应用程序使用扩展JSVGCanvas的自定义查看器JComponent来扩展和显示SVG背景图像。将View类添加到JViewPort后,它应加载SVG图像,调整其大小以适应JViewPort的大小,然后显示图像。
结果应如下所示:
然而,在使用Java 1.7.0_51的MacBook(OS X 10.8.5)上,它如下所示:
在我的Mac上,当我调整应用程序窗口大小(从而激活componentResized方法)时,SVG图像会正确调整大小,如第一张图片所示。
我试过了:
我对这个问题发生的地方感到困惑。如果背景组件的大小已正确设置为1342x552,为什么在调整窗口大小之前图像不会调整大小?
以下是View类的相关部分:
public class View extends JPanel {
private final class BackgroundImageLoader implements AncestorListener {
private ComponentListener listener;
BackgroundImageLoader(final ComponentListener listener) {
this.listener = listener;
}
public void ancestorAdded(AncestorEvent event) {
loadBackgroundImage();
getParent().addComponentListener(listener);
}
public void ancestorRemoved(AncestorEvent event) {
getParent().removeComponentListener(listener);
}
public void ancestorMoved(AncestorEvent event) {
}
}
private JComponent backgroundComponent;
private boolean fitToViewport;
public MapView() {
// Other code...
final String fitToViewportAsString = MapStyle
.getController(modeController).getPropertySetDefault(model,
MapStyle.FIT_TO_VIEWPORT);
fitToViewport = Boolean.parseBoolean(fitToViewportAsString);
final ComponentAdapter backgroundImageResizer =
new ComponentAdapter() {
public void componentResized(ComponentEvent e) {
if (fitToViewport) {
adjustBackgroundComponentScale();
}
}
};
addAncestorListener(new BackgroundImageLoader(backgroundImageResizer));
}
public void mapChanged(final MapChangeEvent event) {
final Object property = event.getProperty();
if (property.equals(MapStyle.RESOURCES_BACKGROUND_IMAGE)) {
loadBackgroundImage();
adjustViewportScrollMode();
}
if (property.equals(MapStyle.FIT_TO_VIEWPORT)) {
final String fitToViewportAsString = MapStyle
.getController(modeController).getPropertySetDefault(model,
MapStyle.FIT_TO_VIEWPORT);
fitToViewport = Boolean.parseBoolean(fitToViewportAsString);
adjustViewportScrollMode();
adjustBackgroundComponentScale();
}
}
private void loadBackgroundImage() {
final MapStyle mapStyle = getModeController().getExtension(MapStyle.class);
final String uriString = mapStyle
.getProperty(model, MapStyle.RESOURCES_BACKGROUND_IMAGE);
backgroundComponent = null;
if (uriString != null) {
URI uri = assignAbsoluteURI(uriString);
final ViewerController vc = getModeController()
.getExtension(ViewerController.class);
final IViewerFactory factory = vc.getCombiFactory();
if (uri != null) {
assignViewerToBackgroundComponent(factory, uri);
}
}
adjustViewportScrollMode();
}
private URI assignAbsoluteURI(final String uriString) {
final UrlManager urlManager = getModeController()
.getExtension(UrlManager.class);
URI uri = null;
try {
uri = urlManager.getAbsoluteUri(model, new URI(uriString));
}
catch (final URISyntaxException e) {
LogUtils.severe(e);
}
catch (MalformedURLException e) {
LogUtils.severe(e);
}
return uri;
}
private void assignViewerToBackgroundComponent(final IViewerFactory factory,
final URI uri) {
try {
final JViewport vp = (JViewport) getParent();
if (vp != null) {
final Dimension viewPortSize = vp.getVisibleRect().getSize();
backgroundComponent = (JComponent) factory
.createViewer(uri, viewPortSize);
}
((ScalableComponent) backgroundComponent).setCenter(true);
((ScalableComponent) backgroundComponent)
.setImageLoadingListener(new ImageLoadingListener() {
public void imageLoaded() {
repaint();
}
});
}
catch (final MalformedURLException e1) {
LogUtils.severe(e1);
}
catch (final IOException e1) {
LogUtils.severe(e1);
}
}
@Override
protected void paintComponent(final Graphics g) {
super.paintComponent(g);
if (backgroundComponent != null) {
paintBackgroundComponent(g);
}
}
private void paintBackgroundComponent(final Graphics g) {
Graphics backgroundGraphics = g.create();
try {
setBackgroundComponentLocation(backgroundGraphics);
backgroundComponent.paint(backgroundGraphics);
}
finally {
backgroundGraphics.dispose();
}
}
private void setBackgroundComponentLocation(Graphics g) {
final JViewport vp = (JViewport) getParent();
final Point viewPosition = vp.getViewPosition();
g.translate(viewPosition.x, viewPosition.y);
}
private void adjustBackgroundComponentScale() {
if (backgroundComponent != null) {
final JViewport vp = (JViewport) getParent();
final Dimension viewPortSize = vp.getVisibleRect().getSize();
((ScalableComponent) backgroundComponent)
.setFinalViewerSize(viewPortSize);
}
}
}
以下是自定义查看器组件的相关部分:
public class SvgViewerFactory implements IViewerFactory {
private ViewerComponent canvas;
private final class ViewerComponent extends
JSVGCanvas implements ScalableComponent {
private static final long serialVersionUID = 1L;
private Dimension originalSize = null;
public void setFinalViewerSize(final Dimension sizeWithScaleCorrection) {
setRenderingTransform(initialTransform);
setPreferredSize(sizeWithScaleCorrection);
setMySize(sizeWithScaleCorrection);
setSize(sizeWithScaleCorrection);
}
public ViewerComponent(final URI uri) {
this(uri, null);
}
public ViewerComponent(final URI uri, final Dimension size) {
super(null, false, false);
setDocumentState(ALWAYS_STATIC);
setSize(1, 1);
addGVTTreeRendererListener(new GVTTreeRendererAdapter() {
@Override
public void gvtRenderingStarted(final GVTTreeRendererEvent e) {
super.gvtRenderingStarted(e);
final SVGDocument document = getSVGDocument();
final SVGSVGElement rootElement = document.getRootElement();
final SVGLength width = rootElement.getWidth().getBaseVal();
final SVGLength height = rootElement.getHeight()
.getBaseVal();
float defaultWidth = (float) Math.ceil(width.getValue());
float defaultHeigth = (float) Math.ceil(height.getValue());
if (defaultWidth == 1f && defaultHeigth == 1f) {
defaultWidth = ResourceController
.getResourceController().getIntProperty(
"default_external_component_width", 200);
defaultHeigth = ResourceController
.getResourceController().getIntProperty(
"default_external_component_height", 200);
}
originalSize = new Dimension
((int) defaultWidth, (int) defaultHeigth);
if ("".equals(rootElement.getAttributeNS(
null, SVGConstants.SVG_VIEW_BOX_ATTRIBUTE))) {
rootElement.setAttributeNS(null,
SVGConstants.SVG_VIEW_BOX_ATTRIBUTE,
"0 0 " + defaultWidth
+ " " + defaultHeigth);
}
if (size == null) {
setSize(originalSize);
}
else {
setSize(size);
}
removeGVTTreeRendererListener(this);
}
});
setURI(uri.toString());
}
@Override
public Dimension getPreferredSize() {
if (originalSize == null) {
return new Dimension(1, 1);
}
return super.getPreferredSize();
}
public void setImageLoadingListener(final ImageLoadingListener listener)
{
addGVTTreeRendererListener(new GVTTreeRendererAdapter() {
@Override
public void gvtRenderingCompleted(GVTTreeRendererEvent e) {
listener.imageLoaded();
}
});
}
}
public ScalableComponent createViewer(final URI uri,
final Dimension preferredSize) {
canvas = new ViewerComponent(uri, preferredSize);
canvas.addGVTTreeRendererListener(new GVTTreeRendererAdapter() {
@Override
public void gvtRenderingCompleted(final GVTTreeRendererEvent e) {
canvas.setFinalViewerSize(preferredSize);
canvas.revalidate();
canvas.removeGVTTreeRendererListener(this);
}
});
return canvas;
}
public ScalableComponent getComponent() {
return canvas;
}
}