JSVGCavas BridgeUserAgent displayError() 覆盖

ele*_*que 0 java xml swing svg batik

我遇到了一个问题,过去两天我一直在苦苦挣扎。我有一个编译的程序,可以运行一些模拟并在 SVG 文件中可视化结果。该文件每 2 秒更换一次新文件,直到模拟完成。

为了可视化结果,我制作了一个 java swing 程序,它使用 batik 和 JSVGCanvas 来显示 svg 文件并每 2 秒更新一次。

我使用的代码是:

// In the main part of my code
svgCanvas = new JSVGCanvas();
oneLineInnerPanel.add("Center", svgCanvas);
(new Thread() {
        @Override
        public void run() {
            try {
                Thread.sleep(2000);
                File f = new File("file_that_shows_simulation_still_running");
                while (f.exists()) {
                    svgReloadButtonActionPerformed(null);
                    Thread.sleep(2000);
                }
            } catch (InterruptedException ex) {
                Logger.getLogger(testUI.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    }).start();
// -----------------------------------------------

private void svgReloadButtonActionPerformed(java.awt.event.ActionEvent evt) {                                                
    try {
        svgCanvas.loadSVGDocument(SVGFile.toURL().toString());

    } catch (MalformedURLException ex) {
        Logger.getLogger(testUI.class.getName()).log(Level.SEVERE, null, ex);
    }
}
Run Code Online (Sandbox Code Playgroud)

它工作正常,但每 30-40 更新一次,loadSVGDocument 会在模拟器写入文档时尝试读取文档,因此我收到 jdialog 错误:

XML 文档结构必须在同一实体内开始和结束。org.apache.batik.dom.util.SAXIOException:XML 文档结构必须在同一实体内开始和结束。在 org.apache.batik.dom.util.SAXDocumentFactory.createDocument(SAXDocumentFactory.java:437) 在 org.apache.batik.dom.util.SAXDocumentFactory.createDocument(SAXDocumentFactory.java:349) 在 org.apache.batik.dom .svg.SAXSVGDocumentFactory.createDocument(SAXSVGDocumentFactory.java:200)在org.apache.batik.dom.svg.SAXSVGDocumentFactory.createSVGDocument(SAXSVGDocumentFactory.java:124)在org.apache.batik.bridge.DocumentLoader.loadDocument(DocumentLoader.java) :106)在org.apache.batik.swing.svg.SVGDocumentLoader.run(SVGDocumentLoader.java:84)

引起的:org.xml.sax.SAXParseException;系统ID:文件:/tmp/tempDir9189341730639722289/svgOut.svg;行号:272;列数:2;XML 文档结构必须在同一实体内开始和结束。在 org.apache.xerces.parsers.AbstractSAXParser.parse(未知来源) 在 org.apache.batik.dom.util.SAXDocumentFactory.createDocument(SAXDocumentFactory.java:431) ... 5 更多

这并不影响整个过程,但它很丑陋。在整个模拟过程中我得到了 2-3 个这样的 jdialogs。我无法锁定文件 I/O,因为我无权访问模拟器代码。如果我仅从 java 锁定,模拟器会崩溃并表示无法访问该文件。

我想要的是,如果加载 svg 文件时出现错误,以某种方式在内部捕获它并且没有 jdialog。我可以接受每 30-40 次(60-80 秒)错过一次更新。

现在,JSVGCanvas 为您提供了提供用户代理并覆盖 displayError() 方法的选项,以按照您的意愿进行操作。我尝试过,但对话框仍然出现。问题是对话框不是由我提供的 svgUserAgent 生成的,而是由内部 BridgeUserAgent 生成的:

public JSVGComponent(SVGUserAgent ua, boolean eventsEnabled,
                     boolean selectableText) {
    super(eventsEnabled, selectableText);

    svgUserAgent = ua;

    userAgent = new BridgeUserAgentWrapper(createUserAgent());

    addSVGDocumentLoaderListener((SVGListener)listener);
    addGVTTreeBuilderListener((SVGListener)listener);
    addSVGLoadEventDispatcherListener((SVGListener)listener);
    if (updateOverlay != null) 
        getOverlays().add(updateOverlay);
}
public void loadSVGDocument(String url) {
    String oldURI = null;
    if (svgDocument != null) {
        oldURI = svgDocument.getURL();
    }
    final ParsedURL newURI = new ParsedURL(oldURI, url);

    stopThenRun(new Runnable() {
            public void run() {
                String url = newURI.toString();
                fragmentIdentifier = newURI.getRef();

                loader = new DocumentLoader(userAgent);
                nextDocumentLoader = new SVGDocumentLoader(url, loader);
                nextDocumentLoader.setPriority(Thread.MIN_PRIORITY);

                Iterator it = svgDocumentLoaderListeners.iterator();
                while (it.hasNext()) {
                    nextDocumentLoader.addSVGDocumentLoaderListener
                        ((SVGDocumentLoaderListener)it.next());
                }
                startDocumentLoader();
            }
        });
}
Run Code Online (Sandbox Code Playgroud)

谁能帮我摆脱这个困境吗?

提前致谢!

ele*_*que 5

终于解决了问题。扩展JSVGCanvas,重写createUserAgent()方法来提供我自己的bridgeuseragent。此用户代理扩展了 JSVGCanvas 用户代理,但覆盖了 displayError 方法。这是代码:

import org.apache.batik.bridge.UserAgent;
import org.apache.batik.swing.JSVGCanvas;
import org.apache.batik.util.XMLConstants;

/**
 *
 * @author
 */
public class myJSVGCanvas extends JSVGCanvas{

@Override
protected UserAgent createUserAgent() {
    return new myCanvasUserAgent();
}

protected class myCanvasUserAgent extends CanvasUserAgent

    implements XMLConstants {

    /**
     * Displays an error message in the User Agent interface.
     */
    @Override
    public void displayError(String message) {
        if (svgUserAgent != null) {
            super.displayError(message);
        } else {
            System.out.println(message);
//            JOptionPane pane =
//                new JOptionPane(message, JOptionPane.ERROR_MESSAGE);
//            JDialog dialog =
//                pane.createDialog(myJSVGCanvas.this, "ERROR");
//            dialog.setModal(false);
//            dialog.setVisible(true); // Safe to be called from any thread
        }
    }

    /**
     * Displays an error resulting from the specified Exception.
     */
    @Override
    public void displayError(Exception ex) {
        if (svgUserAgent != null) {
            super.displayError(ex);
        } else {
            ex.printStackTrace();
//            JErrorPane pane =
//                new JErrorPane(ex, JOptionPane.ERROR_MESSAGE);
//            JDialog dialog = pane.createDialog(myJSVGCanvas.this, "ERROR");
//            dialog.setModal(false);
//            dialog.setVisible(true); // Safe to be called from any thread
        }
    }
}    
}
Run Code Online (Sandbox Code Playgroud)

希望它对某人有帮助。如果有人有更好的想法来处理这个问题,而不仅仅是隐藏它,我很高兴听到!