JUNG:删除边会导致 BasicEdgeRenderer.paintEdge() 抛出 NullPointerException
JUNG: Removing edges results in a NullPointerException thrown from BasicEdgeRenderer.paintEdge()
我正在从线程中动态删除 JUNG 图的边,但这会导致 NullPointerExceptions
。
我看到的堆栈跟踪:
Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
at edu.uci.ics.jung.visualization.renderers.BasicEdgeRenderer.paintEdge(BasicEdgeRenderer.java:51)
at edu.uci.ics.jung.visualization.renderers.BasicRenderer.renderEdge(BasicRenderer.java:78)
at edu.uci.ics.jung.visualization.renderers.BasicRenderer.render(BasicRenderer.java:38)
at edu.uci.ics.jung.visualization.BasicVisualizationServer.renderGraph(BasicVisualizationServer.java:346)
at edu.uci.ics.jung.visualization.BasicVisualizationServer.paintComponent(BasicVisualizationServer.java:301)
at java.desktop/javax.swing.JComponent.paint(JComponent.java:1074)
at java.desktop/javax.swing.JComponent.paintToOffscreen(JComponent.java:5255)
at java.desktop/javax.swing.RepaintManager$PaintManager.paintDoubleBufferedImpl(RepaintManager.java:1643)
at java.desktop/javax.swing.RepaintManager$PaintManager.paintDoubleBuffered(RepaintManager.java:1618)
at java.desktop/javax.swing.RepaintManager$PaintManager.paint(RepaintManager.java:1556)
at java.desktop/javax.swing.RepaintManager.paint(RepaintManager.java:1323)
at java.desktop/javax.swing.JComponent._paintImmediately(JComponent.java:5203)
at java.desktop/javax.swing.JComponent.paintImmediately(JComponent.java:5013)
at java.desktop/javax.swing.RepaintManager.run(RepaintManager.java:865)
at java.desktop/javax.swing.RepaintManager.run(RepaintManager.java:848)
at java.base/java.security.AccessController.doPrivileged(AccessController.java:389)
at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:85)
at java.desktop/javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:848)
at java.desktop/javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:823)
at java.desktop/javax.swing.RepaintManager.prePaintDirtyRegions(RepaintManager.java:772)
at java.desktop/javax.swing.RepaintManager$ProcessingRunnable.run(RepaintManager.java:1884)
at java.desktop/java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:313)
at java.desktop/java.awt.EventQueue.dispatchEventImpl(EventQueue.java:770)
at java.desktop/java.awt.EventQueue.run(EventQueue.java:721)
at java.desktop/java.awt.EventQueue.run(EventQueue.java:715)
at java.base/java.security.AccessController.doPrivileged(AccessController.java:389)
at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:85)
at java.desktop/java.awt.EventQueue.dispatchEvent(EventQueue.java:740)
at java.desktop/java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:203)
at java.desktop/java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:124)
at java.desktop/java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:113)
at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:109)
at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
at java.desktop/java.awt.EventDispatchThread.run(EventDispatchThread.java:90)
这是重现错误的代码片段:
import javax.swing.JFrame;
import edu.uci.ics.jung.algorithms.layout.AbstractLayout;
import edu.uci.ics.jung.algorithms.layout.ISOMLayout;
import edu.uci.ics.jung.graph.Graph;
import edu.uci.ics.jung.graph.SparseGraph;
import edu.uci.ics.jung.graph.util.Graphs;
import edu.uci.ics.jung.visualization.GraphZoomScrollPane;
import edu.uci.ics.jung.visualization.VisualizationViewer;
public class JungRepro {
public static void main(String[] args) throws InterruptedException {
// Create the graph with vertices and edges
Graph<Integer, Integer> graph = Graphs.synchronizedGraph(new SparseGraph<Integer, Integer> ());
final int nbrVertices = 10;
for (int i = 0; i < nbrVertices; i++)
graph.addVertex(i);
int e = 0;
for (int i = 0; i < nbrVertices; i++)
for (int j = 0; j < i; j++)
graph.addEdge(e++, i, j);
AbstractLayout<Integer, Integer> layout = new ISOMLayout<Integer, Integer> (graph);
VisualizationViewer<Integer, Integer> vv = new VisualizationViewer<Integer, Integer> (layout);
JFrame frame = new JFrame ("JungRepro");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new GraphZoomScrollPane (vv));
frame.pack();
frame.setVisible(true);
// Remove edges one by one
while (e >= 0) {
graph.removeEdge(e--);
Thread.sleep(25);
}
}
}
在此先感谢您的帮助!
[编辑:部分重写了问题以反映错误不是由对 repaint()
的调用引起的,而是由对 removeEdge()
的调用引起的。]
您可以尝试从 SwingUtilities.invokeLater 运行 方法内部调用 repaint()。
有几个示例(AddNodeDemo
和 AnimatedAddNodeDemo
)修改了图形并继续更新可视化;你可能想看看他们的例子。
根据以下回复更新
如果你在一个线程上遍历一个非同步的数据结构,并在另一个线程上更新它,你就会遇到这个问题。这与可视化或 JUNG 没有任何关系,这只是 Java.
中有关并发处理的事实
我不是多线程编程方面的专家,但据我所知,如果你不想遇到这个问题,你有两个基本选择:
(1) 控制线程之间的交互,这样您就不会同时更新和迭代图形。
(2) 使用Graphs.synchronized*Graph() 包装您的图形对象。由于我还没有看到您的代码,所以我不能 100% 相信这会起作用,但这可能是最容易尝试的方法。不过,我不确定这将如何影响您的可视化。
如果您确实重新发布了一个更笼统的问题,请提供一个最小的代码片段来重现您的问题。
感谢您张贴您想要执行的简单示例。
下面的代码能达到你想要的效果吗?
public class JungRepro {
public static void main(String[] args) throws Exception {
// Create the graph with vertices and edges
Graph<Integer, Integer> graph = Graphs.synchronizedGraph(new SparseGraph<Integer, Integer>());
final int nbrVertices = 10;
for (int i = 0; i < nbrVertices; i++)
graph.addVertex(i);
int e = 0;
for (int i = 0; i < nbrVertices; i++)
for (int j = 0; j < i; j++)
graph.addEdge(e++, i, j);
AbstractLayout<Integer, Integer> layout = new KKLayout<Integer, Integer>(graph);
VisualizationViewer<Integer, Integer> vv = new VisualizationViewer<Integer, Integer> (layout);
JFrame frame = new JFrame ("JungRepro");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new GraphZoomScrollPane(vv));
frame.pack();
frame.setVisible(true);
// Remove edges one by one
while (graph.getEdgeCount() > 0) {
SwingUtilities.invokeAndWait(() ->
graph.removeEdge(graph.getEdgeCount() - 1)
);
vv.repaint();
Thread.sleep(25);
}
}
}
我正在从线程中动态删除 JUNG 图的边,但这会导致 NullPointerExceptions
。
我看到的堆栈跟踪:
Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
at edu.uci.ics.jung.visualization.renderers.BasicEdgeRenderer.paintEdge(BasicEdgeRenderer.java:51)
at edu.uci.ics.jung.visualization.renderers.BasicRenderer.renderEdge(BasicRenderer.java:78)
at edu.uci.ics.jung.visualization.renderers.BasicRenderer.render(BasicRenderer.java:38)
at edu.uci.ics.jung.visualization.BasicVisualizationServer.renderGraph(BasicVisualizationServer.java:346)
at edu.uci.ics.jung.visualization.BasicVisualizationServer.paintComponent(BasicVisualizationServer.java:301)
at java.desktop/javax.swing.JComponent.paint(JComponent.java:1074)
at java.desktop/javax.swing.JComponent.paintToOffscreen(JComponent.java:5255)
at java.desktop/javax.swing.RepaintManager$PaintManager.paintDoubleBufferedImpl(RepaintManager.java:1643)
at java.desktop/javax.swing.RepaintManager$PaintManager.paintDoubleBuffered(RepaintManager.java:1618)
at java.desktop/javax.swing.RepaintManager$PaintManager.paint(RepaintManager.java:1556)
at java.desktop/javax.swing.RepaintManager.paint(RepaintManager.java:1323)
at java.desktop/javax.swing.JComponent._paintImmediately(JComponent.java:5203)
at java.desktop/javax.swing.JComponent.paintImmediately(JComponent.java:5013)
at java.desktop/javax.swing.RepaintManager.run(RepaintManager.java:865)
at java.desktop/javax.swing.RepaintManager.run(RepaintManager.java:848)
at java.base/java.security.AccessController.doPrivileged(AccessController.java:389)
at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:85)
at java.desktop/javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:848)
at java.desktop/javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:823)
at java.desktop/javax.swing.RepaintManager.prePaintDirtyRegions(RepaintManager.java:772)
at java.desktop/javax.swing.RepaintManager$ProcessingRunnable.run(RepaintManager.java:1884)
at java.desktop/java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:313)
at java.desktop/java.awt.EventQueue.dispatchEventImpl(EventQueue.java:770)
at java.desktop/java.awt.EventQueue.run(EventQueue.java:721)
at java.desktop/java.awt.EventQueue.run(EventQueue.java:715)
at java.base/java.security.AccessController.doPrivileged(AccessController.java:389)
at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:85)
at java.desktop/java.awt.EventQueue.dispatchEvent(EventQueue.java:740)
at java.desktop/java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:203)
at java.desktop/java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:124)
at java.desktop/java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:113)
at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:109)
at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
at java.desktop/java.awt.EventDispatchThread.run(EventDispatchThread.java:90)
这是重现错误的代码片段:
import javax.swing.JFrame;
import edu.uci.ics.jung.algorithms.layout.AbstractLayout;
import edu.uci.ics.jung.algorithms.layout.ISOMLayout;
import edu.uci.ics.jung.graph.Graph;
import edu.uci.ics.jung.graph.SparseGraph;
import edu.uci.ics.jung.graph.util.Graphs;
import edu.uci.ics.jung.visualization.GraphZoomScrollPane;
import edu.uci.ics.jung.visualization.VisualizationViewer;
public class JungRepro {
public static void main(String[] args) throws InterruptedException {
// Create the graph with vertices and edges
Graph<Integer, Integer> graph = Graphs.synchronizedGraph(new SparseGraph<Integer, Integer> ());
final int nbrVertices = 10;
for (int i = 0; i < nbrVertices; i++)
graph.addVertex(i);
int e = 0;
for (int i = 0; i < nbrVertices; i++)
for (int j = 0; j < i; j++)
graph.addEdge(e++, i, j);
AbstractLayout<Integer, Integer> layout = new ISOMLayout<Integer, Integer> (graph);
VisualizationViewer<Integer, Integer> vv = new VisualizationViewer<Integer, Integer> (layout);
JFrame frame = new JFrame ("JungRepro");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new GraphZoomScrollPane (vv));
frame.pack();
frame.setVisible(true);
// Remove edges one by one
while (e >= 0) {
graph.removeEdge(e--);
Thread.sleep(25);
}
}
}
在此先感谢您的帮助!
[编辑:部分重写了问题以反映错误不是由对 repaint()
的调用引起的,而是由对 removeEdge()
的调用引起的。]
您可以尝试从 SwingUtilities.invokeLater 运行 方法内部调用 repaint()。
有几个示例(AddNodeDemo
和 AnimatedAddNodeDemo
)修改了图形并继续更新可视化;你可能想看看他们的例子。
根据以下回复更新
如果你在一个线程上遍历一个非同步的数据结构,并在另一个线程上更新它,你就会遇到这个问题。这与可视化或 JUNG 没有任何关系,这只是 Java.
中有关并发处理的事实我不是多线程编程方面的专家,但据我所知,如果你不想遇到这个问题,你有两个基本选择:
(1) 控制线程之间的交互,这样您就不会同时更新和迭代图形。
(2) 使用Graphs.synchronized*Graph() 包装您的图形对象。由于我还没有看到您的代码,所以我不能 100% 相信这会起作用,但这可能是最容易尝试的方法。不过,我不确定这将如何影响您的可视化。
如果您确实重新发布了一个更笼统的问题,请提供一个最小的代码片段来重现您的问题。
感谢您张贴您想要执行的简单示例。
下面的代码能达到你想要的效果吗?
public class JungRepro {
public static void main(String[] args) throws Exception {
// Create the graph with vertices and edges
Graph<Integer, Integer> graph = Graphs.synchronizedGraph(new SparseGraph<Integer, Integer>());
final int nbrVertices = 10;
for (int i = 0; i < nbrVertices; i++)
graph.addVertex(i);
int e = 0;
for (int i = 0; i < nbrVertices; i++)
for (int j = 0; j < i; j++)
graph.addEdge(e++, i, j);
AbstractLayout<Integer, Integer> layout = new KKLayout<Integer, Integer>(graph);
VisualizationViewer<Integer, Integer> vv = new VisualizationViewer<Integer, Integer> (layout);
JFrame frame = new JFrame ("JungRepro");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new GraphZoomScrollPane(vv));
frame.pack();
frame.setVisible(true);
// Remove edges one by one
while (graph.getEdgeCount() > 0) {
SwingUtilities.invokeAndWait(() ->
graph.removeEdge(graph.getEdgeCount() - 1)
);
vv.repaint();
Thread.sleep(25);
}
}
}