我目前正在尝试创建一个使用apache batik缩放和显示SVG图像的自定义JComponent(ViewerComponent)。目前,ViewerComponent按比例缩放SVG图像;但是,我希望它可以缩放以适应组件的大小,忽略比例。下面的代码显示了我为ViewerComponent编写的一个简单测试。如何修改ViewerComponent以使其表现如上所述?
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();
}
}
答案 0 :(得分:2)
您需要将preserveAspectRatio
属性设置为none
。所以它会是这样的:
rootElement.setAttribute("preserveAspectRatio", "none");
我自己没有以这种方式使用蜡染库,但这是实现此结果的DOM方式。