Java 调整包含JSVGCanvas的JComponent的大小时Batik IllegalStateException
我的程序似乎运行得很好,但我不断遇到非法状态异常:当我尝试调整组件大小时,RunnableQueue未启动或不时退出。我已经将documentState设置为ALWAYS_DYNAMIC,并且我已经了解到您应该使用JSVGCanvas的UpdateManager和调用invokelater。据我所知,在第一次Java 调整包含JSVGCanvas的JComponent的大小时Batik IllegalStateException,java,dom,dynamic,illegalstateexception,batik,Java,Dom,Dynamic,Illegalstateexception,Batik,我的程序似乎运行得很好,但我不断遇到非法状态异常:当我尝试调整组件大小时,RunnableQueue未启动或不时退出。我已经将documentState设置为ALWAYS_DYNAMIC,并且我已经了解到您应该使用JSVGCanvas的UpdateManager和调用invokelater。据我所知,在第一次 gvtBuildCompleted(GVTTreeBuilderEvent e) 调用,因此我在使用它之前检查它是否正在运行,但仍然得到异常。 以下方法被线程重复调用,似乎导致异常: p
gvtBuildCompleted(GVTTreeBuilderEvent e)
调用,因此我在使用它之前检查它是否正在运行,但仍然得到异常。
以下方法被线程重复调用,似乎导致异常:
private void updateDomTree(final SVGComponent component, final Document doc)
{
if(component.getSvgCanvas().getUpdateManager() != null && component.getSvgCanvas().getUpdateManager().isRunning())
{
component.getSvgCanvas().getUpdateManager().getUpdateRunnableQueue().invokeLater(new Runnable()
{
public void run()
{
final Node newNode = doc.getChildNodes().item(0).getFirstChild();
//could be easier to get this value, but ... it works.
String newNodeId = newNode.getAttributes().getNamedItem("id").getFirstChild().getNodeValue();
NodeList nodes = component.getSvgDocument().getDocumentElement().getChildNodes();
Node updateNode = findElementById(nodes, newNodeId);
resizeComponent(component, doc);
component.getSvgCanvas().getSVGDocument().adoptNode(newNode);
component.getSvgCanvas().getSVGDocument().getDocumentElement().replaceChild(newNode, updateNode);
component.refreshSVGCanvas();
}
});
}
}
实际大小调整在此处完成:
protected void resizeComponent(SVGComponent component, Document doc)
{
Element svgRoot = doc.getDocumentElement();
final int svgWidth = Integer.parseInt(svgRoot.getAttribute("width"));
final int svgHeight = Integer.parseInt(svgRoot.getAttribute("height"));
String[] viewBox = svgRoot.getAttribute("viewBox").split(" ");
int viewBoxLeft = Integer.parseInt(viewBox[0]);
int viewBoxTop = Integer.parseInt(viewBox[1]);
final float factor = component.getScaleFactor();
String[] viewBoxOld = component.getSvgDocument().getDocumentElement().getAttribute("viewBox").split(" ");
int viewBoxLeftOld = Integer.parseInt(viewBoxOld[0]);
int viewBoxTopOld = Integer.parseInt(viewBoxOld[1]);
int xDiff = (int) ((viewBoxLeftOld - viewBoxLeft)*factor);
int yDiff = (int) ((viewBoxTopOld - viewBoxTop)*factor);
if ( viewBoxLeftOld != viewBoxLeft ) //If there is additional content left
{
component.setLocation(component.getLocation().x - xDiff, component.getLocation().y);
}
if ( viewBoxTopOld != viewBoxTop ) //If there is additional content right)
{
component.setLocation(component.getLocation().x, component.getLocation().y - yDiff);
}
component.getSvgDocument().getDocumentElement().setAttribute("width",""+svgWidth);
component.getSvgDocument().getDocumentElement().setAttribute("height",""+svgHeight);
component.getSvgDocument().getDocumentElement().setAttribute("viewBox", ""+viewBoxLeft+" "+viewBoxTop+" "+svgWidth+" "+svgHeight);
component.setSize((int)(svgWidth*factor),(int)(svgHeight*factor));
}
方法
refreshJSVGCanvas()
召唤
以下是完整的堆栈跟踪:
Exception in thread "AWT-EventQueue-0" java.lang.IllegalStateException: RunnableQueue not started or has exited
at org.apache.batik.util.RunnableQueue.invokeLater(RunnableQueue.java:277)
at org.apache.batik.swing.svg.AbstractJSVGComponent.updateRenderingTransform(AbstractJSVGComponent.java:1057)
at org.apache.batik.swing.gvt.AbstractJGVTComponent$1.componentResized(AbstractJGVTComponent.java:237)
at java.awt.AWTEventMulticaster.componentResized(Unknown Source)
at java.awt.Component.processComponentEvent(Unknown Source)
at java.awt.Component.processEvent(Unknown Source)
at java.awt.Container.processEvent(Unknown Source)
at java.awt.Component.dispatchEventImpl(Unknown Source)
at java.awt.Container.dispatchEventImpl(Unknown Source)
at java.awt.Component.dispatchEvent(Unknown Source)
at java.awt.EventQueue.dispatchEventImpl(Unknown Source)
at java.awt.EventQueue.access$200(Unknown Source)
at java.awt.EventQueue$3.run(Unknown Source)
at java.awt.EventQueue$3.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
at java.awt.EventQueue$4.run(Unknown Source)
at java.awt.EventQueue$4.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
at java.awt.EventQueue.dispatchEvent(Unknown Source)
at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.run(Unknown Source)
提前感谢,我到处都找了,试了很多,但都找不到解决办法
编辑:
这是Batik的invokeLater方法,其中实际引发了异常:
public void invokeLater(Runnable r) {
if (runnableQueueThread == null) {
throw new IllegalStateException
("RunnableQueue not started or has exited");
}
synchronized (list) {
list.push(new Link(r));
list.notify();
}
}
runnableQueueThrad在该类的run方法内设置,并在末尾设置为null。
因此,我想我必须进行某种同步。猜一猜,公共void运行代码不应该在另一个方法中,实际上是一个线程类/接口对象,即所谓的构造函数接口版本 把它移到它自己的类别。嵌套子类以保留作用域并在类上实现线程可运行接口,从而将run方法放置在类中以供使用
Stack trace说run方法不可用,因为它实际上没有这样的方法,或者至少没有正确声明,所以它处于非法状态。不幸的是,这不起作用。我已经编辑了我的问题,并在Batik中添加了引发异常的实际行
public void invokeLater(Runnable r) {
if (runnableQueueThread == null) {
throw new IllegalStateException
("RunnableQueue not started or has exited");
}
synchronized (list) {
list.push(new Link(r));
list.notify();
}
}