JSVGCavas BridgeUserAgent переопределение displayError()

Я столкнулся с проблемой, и я боролся последние 2 дня. У меня есть скомпилированная программа, которая запускает некоторые симуляции и визуализирует результаты в файле SVG. Файл заменяется каждые 2 секунды на новый, пока симуляция не будет завершена.

Желая визуализировать результаты, я создал java-программу, которая использует батик и 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);
    }
}

Он работает нормально, за исключением того, что каждые 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.jatig.ached. atb. atb. atb. atb.basek) .svg.SAXSVGDocumentFactory.createDocument(SAXSVGDocumentFactory.java:200) в org.apache.batik.dom.svg.SAXSVGDocumentFactory.createSVGDocument(SAXSVGDocumentFactory.jocumentLo.batio.bb.java_jb::106) at org.apache.batik.swing.svg.SVGDocumentLoader.run(SVGDocumentLoader.java:84)

Вызывается: org.xml.sax.SAXParseException; systemId: file:/tmp/tempDir9189341730639722289/svgOut.svg; номер строки: 272; columnNumber: 2; Структуры XML-документов должны начинаться и заканчиваться в одной и той же сущности. в org.apache.xerces.parsers.AbstractSAXParser.parse(неизвестный источник) в org.apache.batik.dom.util.SAXDocumentFactory.createDocument(SAXDocumentFactory.java:431) ... еще 5

Это не влияет на всю процедуру, но это ужасно. Я получаю 2-3 таких журнала во время симуляции. Я не могу заблокировать файловый ввод / вывод, потому что у меня нет доступа к коду симулятора. Если я блокирую только из Java, симулятор падает, говоря, что он не может получить доступ к файлу.

Я хочу, чтобы при загрузке файла svg возникла ошибка, чтобы он каким-то образом перехватил его и не имел jdialog. Я могу принять пропущенное обновление каждые 30-40 раз (60-80 секунд) .

Теперь JSVGCanvas дает вам возможность предоставить useragent и переписать метод 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();
            }
        });
}

Может кто-нибудь помочь мне выбраться из этого беспорядка, пожалуйста?

Заранее спасибо!

1 ответ

Решение

Наконец-то решена проблема. Расширенный JSVGCanvas, переопределите метод createUserAgent(), чтобы предоставить мой собственный бридж-агент. Этот пользовательский агент расширяет пользовательский агент 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
        }
    }
}    
}

Надеюсь, это кому-нибудь поможет. Если у кого-то есть лучшая идея для решения проблемы, чем просто ее скрыть, я буду рад это услышать!

Другие вопросы по тегам