2014-03-01 82 views
1

我目前正在嘗試創建一個使用apache batik來縮放和顯示SVG圖像的自定義JComponent(ViewerComponent)。當前ViewerComponent按比例縮放SVG圖像;不過,我希望它可以按比例縮放以適應組件的大小。下面的代碼顯示了我爲ViewerComponent編寫的一個簡單測試。我怎樣才能修改它的ViewerComponent行爲如上所述?如何在使用Apache Batik縮放SVG圖像時忽略比例?

import java.awt.*; 
import java.awt.event.*; 
import java.net.*; 
import javax.swing.*; 
import org.apache.batik.swing.*; 
import org.apache.batik.swing.gvt.*; 
import org.apache.batik.util.*; 
import org.w3c.dom.svg.*; 

public final class View extends JPanel { 

    public static final Dimension VIEW_SIZE = new Dimension(2000, 2000); 
    public static final Dimension WINDOW_SIZE = new Dimension(600, 600); 
    public static final String BACKGROUND_IMAGE 
      = "file:///Users/home/Desktop/wiki.svg"; 

    private JScrollPane scrollPane; 
    private ViewerComponent canvas; 

    View() throws URISyntaxException { 
     setUpGUI(); 
     createViewerBasedOnViewportSize(); 
    } 

    private void setUpGUI() throws HeadlessException { 
     setUpView(); 
     setUpScrollPane(); 
     setUpFrame(); 
    } 

    private void setUpView() { 
     this.setPreferredSize(VIEW_SIZE); 
     this.setBackground(Color.WHITE); 
    } 

    private void setUpScrollPane() { 
     scrollPane = new JScrollPane(this); 
    } 

    private void setUpFrame() throws HeadlessException { 
     JFrame frame = new JFrame("SVG Viewer Test"); 
     frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); 
     frame.setContentPane(scrollPane); 
     frame.setPreferredSize(WINDOW_SIZE); 
     frame.setLocationByPlatform(true); 
     frame.pack(); 
     frame.setVisible(true); 
     frame.addComponentListener(new ComponentAdapter() { 
      @Override 
      public void componentResized(ComponentEvent e) { 
       adjustBackgroundComponentScale(); 
       repaint(); 
      } 
     }); 
    } 

    private void adjustBackgroundComponentScale() { 
     if (canvas != null) { 
      Dimension windowSize = calculateWindowSize(); 
      canvas.setFinalViewerSize(windowSize); 
     } 
    } 

    private void createViewerBasedOnViewportSize() throws URISyntaxException { 
     Dimension windowSize = calculateWindowSize(); 
     URI uri = retrieveURI(); 
     createViewer(uri, windowSize); 
    } 

    private Dimension calculateWindowSize() { 
     final JViewport vp = (JViewport) getParent(); 
     final Dimension windowSize = vp.getVisibleRect().getSize(); 
     return windowSize; 
    } 

    private URI retrieveURI() throws URISyntaxException { 
     URI uri = new URI(BACKGROUND_IMAGE); 
     return uri; 
    } 

    void createViewer(final URI uri, 
      final Dimension preferredSize) { 
     canvas = new ViewerComponent(uri); 
     canvas.addGVTTreeRendererListener(new GVTTreeRendererAdapter() { 
      @Override 
      public void gvtRenderingCompleted(final GVTTreeRendererEvent e) { 
       canvas.setFinalViewerSize(preferredSize); 
       canvas.revalidate(); 
       canvas.removeGVTTreeRendererListener(this); 
      } 
     }); 
    } 

    @Override 
    public void paintComponent(Graphics g) { 
     super.paintComponent(g); 
     if (canvas != null) { 
      setAndPaintViewer(g); 
     } 
    } 

    private void setAndPaintViewer(Graphics g) { 
     Graphics backgroundGraphics = g.create(); 
     try { 
      setBackgroundComponentLocation(backgroundGraphics); 
      canvas.paint(backgroundGraphics); 
      repaint(); 
     } finally { 
      backgroundGraphics.dispose(); 
     } 
    } 

    private void setBackgroundComponentLocation(Graphics g) { 
     final JViewport vp = (JViewport) getParent(); 
     final Point viewPosition = vp.getViewPosition(); 
     g.translate(viewPosition.x, viewPosition.y); 
    } 

    public static void main(String[] args) { 
     SwingUtilities.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       try { 
        new View(); 
       } catch (URISyntaxException ex) { 
        ex.printStackTrace(); 
       } 
      } 
     }); 
    } 

} 

class ViewerComponent extends JSVGCanvas { 

    private static final long serialVersionUID = 1L; 
    private Dimension originalSize = null; 

    public Dimension getOriginalSize() { 
     return new Dimension(originalSize); 
    } 

    public void setFinalViewerSize(final Dimension size) { 
     final JSVGCanvas canvas = this; 
     canvas.setPreferredSize(size); 
     canvas.setMySize(size); 
     canvas.setSize(size); 
    } 

    public void setDraftViewerSize(final Dimension size) { 
     setFinalViewerSize(size); 
    } 

    public void setFinalViewerSize(final float zoom) { 
     int scaledWidth = (int) (originalSize.width * zoom); 
     int scaledHeight = (int) (originalSize.height * zoom); 
     setFinalViewerSize(new Dimension(scaledWidth, scaledHeight)); 
    } 

    public ViewerComponent(final URI uri) { 
     super(null, false, false); 
     setDocumentState(ALWAYS_STATIC); 
     setSize(1, 1); 
     setRecenterOnResize(true); 
     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 = 200; 
        defaultHeigth = 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); 
       } 
       setSize(originalSize); 
       removeGVTTreeRendererListener(this); 
      } 
     }); 
     setURI(uri.toString()); 
    } 

    @Override 
    public Dimension getPreferredSize() { 
     if (originalSize == null) { 
      return new Dimension(1, 1); 
     } 
     return super.getPreferredSize(); 
    } 

} 

回答

2

你需要的preserveAspectRatio屬性設置爲none。因此,這將是這樣的:

rootElement.setAttribute("preserveAspectRatio", "none"); 

我沒有用蠟染庫這樣自己,但這是實現這一結果的DOM方法。

+0

它的工作原理就是我想要的。謝謝。 – kshikama