Search code examples
javaapachesvgbatik

JSVGCanvas does not update the graphic after new elements being added


using: Apache batik (SVG) , NetBeans IDE, NetBeans platform, Java

I have an application with a SVG displayed with batik and the JSVGCanvas Component.

I also called svg.setDocumentState(JSVGCanvas.ALWAYS_DYNAMIC);

This is the SVG file:

<svg width="500" height="400" viewBox="0 0 250 200" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="hi" style="color:black; stroke:currentColor; stroke-width:0.4;">
    <g id="ks">
        <text id="textX" x="0" y="5" style="font-family:Arial; font-size:4.00pt; text-anchor:start">100%</text>
        <text id="textY" x="5" y="105" style="font-family:Arial; font-size:4.00pt; text-anchor:start">0%</text>
    </g>
</g>

This simple SVG is first displayed in the application just like it is now. Now I get new input from the application and need to add new Elements to the SVG document. I am doing this with the SVGDocument, which i get from JSVGCanvas. Here is an example:

Runnable run = new Runnable()
{
  @Override
  public void run()
  {
      Element elementById = SVGUtilities.getElementById(svgDocument, "g", "hi");
      Element createElement = svgDocument.createElement("g");
      createElement.setAttribute("id", "myID");
      Element rect = SVGUtilities.createRect(
        svgDocument, String.valueOf(xValue), yValue, String.valueOf(BARWIDTH), 
        String.valueOf(barHeight), color);
      createElement.appendChild(rect);
      elementById.appendChild(createElement);
  }
};

To execute the changes I now wrap these lines in a Runnable and put it in the UpdateManager Queue.

RunnableQueue updateRunnableQueue = updateManager.getUpdateRunnableQueue();
updateRunnableQueue.invokeAndWait(run);
((JSVGCanvas)canvas).setSVGDocument((SVGDocument)doc);

The JSVGCanvas does not update the graphic.

Some additional information:

  • I tried it also with invokeLater(run); this did not work, too
  • I DON´T change the file, JUST the SVGDocument. So I do not write the changes to the file. I just change the "Document" instance.
  • I printed the document instance to the console for logging and the result is exactly what i wanted, so the document DOES contain the right and new elements.

The result for the SVG in the console is:

<svg xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" contentScriptType="text/ecmascript" width="500" zoomAndPan="magnify" contentStyleType="text/css" viewBox="0 0 250 200" height="400" preserveAspectRatio="xMidYMid meet" version="1.0">
<g style="color:black; stroke:currentColor; stroke-width:0.4;" id="hi">
    <g id="ks">
        <text x="0" id="textX" y="5" style="font-family:Arial; font-size:4.00pt; text-anchor:start">100%</text>
        <text x="5" id="textY" y="105" style="font-family:Arial; font-size:4.00pt; text-anchor:start">0%</text>
    </g>
<g id="25.0">
        <rect x="20.0" width="20.0" y="5.0" height="7.142857142857142" style="fill:#ff0000"/>
    </g>
</g>

Do you have any idea why my graphic does not update? I searched for days now and my changes (UpdateManager Queue, setSVGDocument, etc.) do not work. I dont know what to do now...

Thank you in advance.

Greetings Tobias


Solution

  • SVG elements must be created in the SVG namespace. They cannot therefore be created using createElement and must be created using createElementNS

    Element createElement = svgDocument.createElement("g");
    

    is incorrect, it needs to be written like this...

    Element createElement = svgDocument.createElementNS(SVGDOMImplementation.SVG_NAMESPACE_URI, "g");
    

    I'm not sure what SVGUtilities does since you haven't provided that implementation but that may be wrong too.