2012-08-12 34 views
0

在构建简单家族树应用程序并使用Jung绘制图表时,会遇到错误。到目前为止,我能够使用zentus中的sqlitejdbc绘制图表并将其保存到嵌入式数据库中。我还没有创建函数来清除画布,所以我必须重新启动应用程序来测试打开数据库。但是当我想加载它们时,应用程序就会冻结,我遇到了这个错误。当从数据库加载顶点和边时,顶点画家遇到错误

path:C:\Users\PaLi\Desktop\psm things\chart4.db 
    Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException 
at FamTree.vertexPainter.transform(vertexPainter.java:20) 
at FamTree.vertexPainter.transform(vertexPainter.java:1) 
at edu.uci.ics.jung.visualization.renderers.BasicVertexRenderer.paintShapeForVertex(BasicVertexRenderer.java:98) 
at edu.uci.ics.jung.visualization.renderers.BasicVertexRenderer.paintIconForVertex(BasicVertexRenderer.java:74) 
at edu.uci.ics.jung.visualization.renderers.BasicVertexRenderer.paintVertex(BasicVertexRenderer.java:37) 
at edu.uci.ics.jung.visualization.renderers.BasicRenderer.renderVertex(BasicRenderer.java:70) 
at edu.uci.ics.jung.visualization.renderers.BasicRenderer.render(BasicRenderer.java:55) 
at edu.uci.ics.jung.visualization.BasicVisualizationServer.renderGraph(BasicVisualizationServer.java:367) 
at edu.uci.ics.jung.visualization.BasicVisualizationServer.paintComponent(BasicVisualizationServer.java:321) 
at javax.swing.JComponent.paint(JComponent.java:1054) 
at javax.swing.JComponent.paintToOffscreen(JComponent.java:5221) 
at javax.swing.RepaintManager$PaintManager.paintDoubleBuffered(RepaintManager.java:1482) 
at javax.swing.RepaintManager$PaintManager.paint(RepaintManager.java:1413) 
at javax.swing.RepaintManager.paint(RepaintManager.java:1206) 
at javax.swing.JComponent._paintImmediately(JComponent.java:5169) 
at javax.swing.JComponent.paintImmediately(JComponent.java:4980) 
at javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:770) 
at javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:728) 
at javax.swing.RepaintManager.prePaintDirtyRegions(RepaintManager.java:677) 
at javax.swing.RepaintManager.access$700(RepaintManager.java:59) 
at javax.swing.RepaintManager$ProcessingRunnable.run(RepaintManager.java:1621) 
at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:251) 
at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:705) 
at java.awt.EventQueue.access$000(EventQueue.java:101) 
at java.awt.EventQueue$3.run(EventQueue.java:666) 
at java.awt.EventQueue$3.run(EventQueue.java:664) 
at java.security.AccessController.doPrivileged(Native Method) 
at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76) 
at java.awt.EventQueue.dispatchEvent(EventQueue.java:675) 
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:211) 
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:128) 
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:117) 
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:113) 
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:105) 
at java.awt.EventDispatchThread.run(EventDispatchThread.java:90) 

这是顶点画家变压器的代码。如果没有加载数据库部分,它工作得很好。

package FamTree; 

import org.apache.commons.collections15.Transformer; 

import java.awt.*; 
import java.util.Map; 

class vertexPainter implements Transformer<Integer, Paint> 
{ 
private Map<Integer,Person> tempV; 

public vertexPainter(Map<Integer,Person> passV) 
{ 
    tempV = passV; 
} 
public Paint transform(Integer v) 
{ 

    if (tempV.get(v).getpSex().equalsIgnoreCase("male")) 
     return (Color.blue); 
    else 
    return (Color.red); 

} 
} 

这是图的初始化和设置vv。

 public TCanvas(){ 

    graph = new SparseMultigraph<Integer,Number>(); 

    layout2 = new StaticLayout<Integer,Number>(graph,new Dimension(2000,2000)); 

    vv = new VisualizationViewer<Integer,Number>(layout2); 
    vv.setBackground(Color.white); 
    vv.setVertexToolTipTransformer(new ToStringLabeller<Integer>()); 
    vv.getRenderContext().setVertexFillPaintTransformer(new vertexPainter(vertex)); 
vv.getRenderer().getVertexLabelRenderer().setPosition(Renderer.VertexLabel.Position.S); 
    vv.getRenderContext().setVertexLabelTransformer(new vertexLabel(vertex)); 
    vv.getRenderContext().setEdgeDrawPaintTransformer(new edgePainter()); 

    Transformer<Number,String> stringer = new Transformer<Number,String>(){ 
     public String transform(Number e) { 
      return "Edge:"+e+ "-"+graph.getEndpoints(e).toString(); 
     } 
    }; 

    vv.getRenderContext().setEdgeLabelTransformer(stringer); 

    EdgeLabelRenderer edgeLabelRenderer= vv.getRenderContext().getEdgeLabelRenderer(); 
    edgeLabelRenderer.setRotateEdgeLabels(false); 



    gm = new DefaultModalGraphMouse<Integer, Number>(); 
    vv.setGraphMouse(gm); 
    gm.add(new PopupGraphMousePlugin()); 

    GraphZoomScrollPane scrollPane2 = new GraphZoomScrollPane(vv); 

    JPanel vvPanel = new JPanel(); 
    vvPanel.setLayout(new BorderLayout()); 
    vvPanel.add(scrollPane2); 

    addBottomControls(vvPanel); 

    Container content = getContentPane(); 
    content.add(vvPanel); 
    }//TCanvas() 

这是加载数据库的部分。

 menu.add(new AbstractAction("Open") { 
     public void actionPerformed(ActionEvent e) { 

      JFileChooser open = new JFileChooser(); 
      final File file ; 

      int vat = open.showOpenDialog(rootPane); 

      if(vat==JFileChooser.APPROVE_OPTION){ 

       file = open.getSelectedFile(); 

       String fPath = file.getAbsolutePath(); 

       System.out.println("path:"+fPath); 
       try{ 

        Class.forName("org.sqlite.JDBC"); 
        Connection conn = DriverManager.getConnection("jdbc:sqlite:"+fPath); 

        Statement stat = conn.createStatement(); 

        ResultSet rs = stat.executeQuery("select * from Person;"); 
        while (rs.next()) { 


         Integer pid = rs.getInt("pID"); 
         String pname = rs.getString("pName"); 
         String psex = rs.getString("pSex"); 
         Integer fatherid = (Integer)rs.getInt("fatherID"); 
         Integer motherid = (Integer)rs.getInt("motherID"); 
         Integer spouseid = (Integer)rs.getInt("spouseID"); 

         Person personInfo = new Person(); 

         personInfo.setpID(pid); 
         personInfo.setpName(pname); 
         personInfo.setpSex(psex); 
         personInfo.setFatherID(fatherid); 
         personInfo.setMotherID(motherid); 
         personInfo.setSpouseID(spouseid); 

         vertex.put(pid,personInfo); 
         graph.addVertex(pid); 
         vv.repaint(); 

         ResultSet rs2 = stat.executeQuery("select * from Location;"); 
         while (rs2.next()) { 

          if(rs2.getInt("pID")==pid){ 

           Point2D.Double loc = new Point2D.Double(); 

           Double x = rs2.getDouble("pointX"); 
           Double y = rs2.getDouble("pointY"); 
           loc.setLocation(x, y); 

           layout2.setLocation(pid, vv.getRenderContext().getMultiLayerTransformer().inverseTransform(loc)); 
           vv.repaint(); 
          } 
         } 
         rs2.close(); 


        } 
        rs.close(); 

        ResultSet rs3 = stat.executeQuery("select * from Relation;"); 

        while (rs3.next()) { 

         Point2D.Double loc2 = new Point2D.Double(); 

         Number edgeid = (Number)rs3.getInt("edgeID"); 
         Integer v1 = rs3.getInt("vertex1"); 
         Integer v2 = rs3.getInt("vertex2"); 
         String type = rs3.getString("RelationType"); 

         Relation relation = new Relation(edgeid, v1, v2, type); 
         edge.put(edgeid, relation); 
         if(type.equalsIgnoreCase("DIRECTED")){ 
          graph.addEdge(edgeid, v1, v2, EdgeType.DIRECTED); 
         } 
         if(type.equalsIgnoreCase("UNDIRECTED")){ 
          graph.addEdge(edgeid, v1, v2, EdgeType.UNDIRECTED); 
         } 
         vv.repaint(); 


        } 
        rs3.close(); 

        conn.close(); 
        vv.repaint(); 

       } 
       catch (Exception ex) { 
        // TODO: handle exception 
        ex.printStackTrace(); 
       } 

      } 

     }}); 

我真的不知道这里发生了什么,因为我很确定打开和检索数据库部分没有问题。

回答

1

vertexPainter#transform,无论是地图null或者它对于整数键(“v”)或值pSex属性一个记录中没有值为null(可能未设置数据库表)。

一个调试器可以告诉你究竟是什么实际问题。


TCanvas构造函数中,我看到这行代码:

vv.getRenderContext().setVertexFillPaintTransformer(new vertexPainter(vertex)); 

这就是你创建一个带有地图的画家,但我没有看到地图的声明和初始化。所以很有可能你将一张空白的地图传递给画家,因此画家找不到一个键值(因为地图是空的)。这将明确地导致NPE。


这不是关于研究错误日志。在蚀:

  1. 切换到调试perpsective
  2. 找到关于该视图中的“断点”视图(在右上角通常为标签)
  3. 有一个与一个“J”和惊叹号的按钮标记,工具提示说“添加Java异常断点”
  4. 点击该按钮并输入NPE,然后选择NullPointerException异常
  5. 现在你有一个断点,将停止对每一个空指针异常
  6. 调试applicati (如“运行”)
  7. 最终,应用程序将暂停,您将在“调试”视图中看到堆栈跟踪。一个框架它vertexPainter,选择该行,它会带你到投掷NPE的代码行。现在您必须查看变​​量值并使用检查功能。
+0

我找不到问题。当我启动应用程序并从空白处绘制图形时,它工作正常。所以根据我的理解,从数据库中绘制顶点和边的负载的机制应该是相同的。 – 2012-08-12 14:11:12

+1

调试。希望你使用ide:设置一个断点来停止NullPointerExceptions并检查变量。我指出的其中一个是'null'。 – 2012-08-12 14:14:17

+0

我使用eclipse indigo ide。我不明白你想要我做什么。我该如何停止NullPointerExceptions?对不起,我真的不知道如何使用错误日志进行调试。 – 2012-08-12 14:20:50