Java 为什么不使用ApacheBatik和Mac渲染器调整SVG图像的大小?

Java 为什么不使用ApacheBatik和Mac渲染器调整SVG图像的大小?,java,apache,svg,resize,batik,Java,Apache,Svg,Resize,Batik,目前,我正在使用一个应用程序,该应用程序使用扩展JSVGCanvas的自定义查看器JComponent来缩放和显示SVG背景图像。将View类添加到JViewPort后,它应该加载SVG图像,调整其大小以适合JViewPort的大小,然后显示图像 结果应如下所示: 然而,在我使用Java 1.7.0_51的MacBook(OS X 10.8.5)上,结果如下: 在我的Mac电脑上,当我调整应用程序窗口的大小(从而触发ComponentResistized方法)时,SVG图像将正确调整大小,如

目前,我正在使用一个应用程序,该应用程序使用扩展JSVGCanvas的自定义查看器JComponent来缩放和显示SVG背景图像。将View类添加到JViewPort后,它应该加载SVG图像,调整其大小以适合JViewPort的大小,然后显示图像

结果应如下所示:

然而,在我使用Java 1.7.0_51的MacBook(OS X 10.8.5)上,结果如下:

在我的Mac电脑上,当我调整应用程序窗口的大小(从而触发ComponentResistized方法)时,SVG图像将正确调整大小,如第一张图片所示

我试过:

  • 在调用loadBackgroundImage()后添加对adjustBackgroundComponentScale()的调用
  • 使用三种不同的SVG图像,它们的行为都如第二幅图所示——这意味着图像本身不是问题所在
  • 向paintComponent方法添加断点。backgroundComponent的大小为1342x552,即视口的大小。然而,gvtrout>边界显示为399 x 397(近似于图像的原始大小-意味着图像没有缩放)
我对这个问题发生在哪里感到困惑。如果背景组件的大小已正确设置为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;
    }
}

听起来你的代码很管用。您只需确定加载视图后触发了什么事件或调用了什么方法,然后调用/附加adjustBackgroundComponentScale()。不幸的是,在ancestorAdded(AncestorEvent事件)方法中加载BackgroundImage后调用adjustBackgroundComponentScale不会影响结果。