2013-09-24 2 views
0

JTable 헤더에 툴팁을 추가하려고합니다. 이 경우에는 JTableHeader Java 클래스를 확장하는 TTHeader 클래스를 사용합니다. 다 잘된 것 같지만, JTable에 새로운 TTHeader 헤더를 추가하려고하면 알 수없는 소스로 NullPointerException이 발생합니다. 나는 이유를 모른다. TTHeader 클래스는 괜찮은 것 같습니다. 문제가 다른 곳에서 발생했습니다.setTableHeader() 메서드가 NullPointerException을 throw하는 이유는 무엇입니까?

내 접근 방식은 다음과 같습니다. JTable의 채우기 위해 :

private JPanel contentPane; 
private JScrollPane scrollPane; 
private JTable table; 
private String tooltipsSDB[] = {"SessionID", "UserID", "PatientID", "PluginID", "Date", "Time"}; 

Connection conn = null; 
ResultSet rs = null; 
PreparedStatement ps = null; 

Table() { 
     // Connection Component 
     conn = ConnectionJDBC.ConnectDB(); 

     setTitle("My sample table"); 
     setSize(new Dimension(400, 400)); 
     setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     setLocationRelativeTo(null); 
     setVisible(true); 

     contentPane = new JPanel(); 
     contentPane.setLayout(new BorderLayout(0, 0)); 
     setContentPane(contentPane); 

     scrollPane = new JScrollPane(); 
     contentPane.add(scrollPane, BorderLayout.CENTER); 

     table = new JTable() { 
      public boolean isCellEditable(int row, int column) { 
       return false; 
      }; 
     }; 
     table.setAutoCreateRowSorter(true); 
     // Populate JTable with data from SQL DB 
     populateTable(); 
     scrollPane.setViewportView(table); 
} 

public void populateTable() { 
     String sql = "SELECT * FROM " + ExampleDatabase + " ORDER BY " + ExampleData + " DESC"; 
     try { 
      // Make Connection With DB 
      ps = conn.prepareStatement(sql); 
      rs = ps.executeQuery(); 
      ResultSetMetaData rsmetadata = rs.getMetaData(); 

      // Populate JTable 
      int columns = rsmetadata.getColumnCount(); 
      DefaultTableModel dtm = new DefaultTableModel(); 
      Vector columns_name = new Vector(); 
      Vector data_rows = new Vector(); 
      for (int i = 1; i <= columns; i++) { 
       columns_name.addElement(rsmetadata.getColumnName(i)); 
      } 
      dtm.setColumnIdentifiers(columns_name); 
      while (rs.next()) { 
       data_rows = new Vector(); 
       for (int j = 1; j <= columns; j++) { 
        data_rows.addElement(rs.getString(j)); 
       } 
       dtm.addRow(data_rows); 
      } 
      table.setModel(dtm); 

      // Create Header For JTable 
      TTHeader tth = new TTHeader(table.getColumnModel()); 
      tth.setToolTipStrings(tooltipsSDB); 
      table.setTableHeader(tth); // On This Line I Get NullPointerException With Uknown Source 

      table.repaint(); 
     } catch (SQLException e) { 
      JOptionPane.showMessageDialog(null, "Populate table error! \n" + e); 

     } 
} 

public static void main(String args[]) { 
     EventQueue.invokeLater(new Runnable() { 
      public void run() { 
       try { 
        new Table(); 
       } catch (Exception e) { 
        JOptionPane.showMessageDialog(null, e); 
       } 
      } 
     }); 
} 

그리고 TTHeader 클래스 : 나는 JComboBox의에서 두 번째 데이터베이스를 선택하면

String[] toolTips; 

public TTHeader(TableColumnModel model) { 
    super(model); 
} 

public String getToolTipText(MouseEvent e) { 
    int col = columnAtPoint(e.getPoint()); 
    int modelCol = getTable().convertColumnIndexToModel(col); 
    String retStr; 
    try { 
     retStr = toolTips[modelCol]; 
    } catch (NullPointerException ex) { 
     retStr = ""; 
    } catch (ArrayIndexOutOfBoundsException ex) { 
     retStr = ""; 
    } 
    if (retStr.length() < 1) { 
     retStr = super.getToolTipText(e); 
    } 
    return retStr; 
} 

public void setToolTipStrings(String[] toolTips) { 
    this.toolTips = toolTips; 
} 

NPE가 나타납니다. JComboBox Listener에서 populateTable() 메서드를 호출합니다. 여기에보다 구체적인 스택 트레이스는 다음과 같습니다

Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException 
at mypackage.TTHeader.getToolTipText(TTHeader.java:19) 
at javax.swing.ToolTipManager$insideTimerAction.actionPerformed(Unknown Source) 
at javax.swing.Timer.fireActionPerformed(Unknown Source) 
at javax.swing.Timer$DoPostEvent.run(Unknown Source) 
at java.awt.event.InvocationEvent.dispatch(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.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) 

라인 NR 19 : 당신은 NPE를 얻을 라인을 확인하면

int modelCol = getTable().convertColumnIndexToModel(col); 
+0

우선'e.printStackTrace()'를'catch' 블록에 추가하여'exception' 세부 사항을 얻은 다음 게시물에 추가하고 그 라인을 가리 키도록하십시오. – Smit

+0

NPE가있는 곳이 아니라고 거의 확신합니다. –

+0

plz post stacktrace – exexzian

답변

1

, 당신은 확인 먼저이 역 참조 연산자의 모든 항목입니다 (.) . 해당 연산자의 왼쪽에있는 값 (!)은 null입니다. (당신이. 다음, 한 줄에 그 중 하나 여러 .의가 있다면 그래서 당신의 라인은 foo.getBar().doSomething()입니다, 하나 foonull 또는 foo.getBar() 반환 null. 그러나 doSomething() 반환 문제가되지 않습니다. 경우)를이 경우

null을 반환하는 getTable() 메서드 일 수 있습니다. fooCollection가 null의 경우 여기에 당신이 NPE를 얻을 for (Foo foo : fooCollection)에서

  1. 암시 역 참조 :

    은 자바 5 이후 NPE의 두 가지 새로운 오히려 더 비열한 수 원인이되고있다. 숫자의

  2. 자동 언 박싱 : Integer i = null; int j = i + 1; //NPE here

당신이 일반적으로 NPEs의 디버깅에 대해 알아야 할 모든이다, 물론 당신이 변수 값을 기록하거나 디버거를 사용해야 중 하나를 더 일반적인 조언있다 코드를 단계별로 실행하십시오.

+1

그리고 그 경우입니다. JTable 초기화를 populateTable() 메소드로 옮겼다. 그리고 사용자가 원하는 DB를 선택할 때마다 JTable이 처음부터 초기화된다. 그러나 나는 한 가지를 이해하지 못합니다. 왜 NPE를 처음에 얻습니까? 이미 초기화 된 테이블에 대해 getTable()을 사용 했으므로 ... – bluevoxel

+0

정확한 답변을 제공하기 위해 코드를 더 많이보아야하지만 일반적으로 스윙 응용 프로그램은 멀티 스레드이므로 마음에 들지 않습니다. 한 스레드에 대해 - null은주의하지 않으면 다른 null에 대해 쉽게 null 수 있습니다. – biziclop

+0

이것은 존재하는 것 중 최악의 예이며 JDBC에서 채워진 JTable에 문제가 있습니다. – mKorbel

관련 문제