为什么setTableHeader()方法抛出NullPointerException?

时间:2013-09-24 15:51:10

标签: java swing nullpointerexception jtable jtableheader

我尝试将工具提示添加到我的JTable标头中。在这种情况下,我使用TTHeader类扩展了JTableHeader Java类。它看起来很好,但是当我尝试向我的JTable添加新的TTHeader标头时,我得到的是带有Unknown Source的NullPointerException。我不知道为什么。 TTHeader类似乎没问题。问题出在其他地方。

这是我的方法的代码。 对于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课程:

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;
}

当我从JComboBox中选择第二个数据库时出现NPE。在JComboBox监听器中,我调用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)

第19行:

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

1 个答案:

答案 0 :(得分:1)

当您获得NPE并识别该行时,您首先检查的是所有出现的解除引用运算符(.)。这样的运算符的左侧(!)的值将是null。 (如果您在一行中有多个.,那么其中一行。如果您的行是foo.getBar().doSomething(),则foonullfoo.getBar()会返回null。但doSomething()返回的内容并不重要。)

在这种情况下,可能是返回getTable()的{​​{1}}方法。

自从Java 5出现了两个新的,更可能是偷偷摸摸的 NPE的原因:

  1. null中的隐式解除引用,如果for (Foo foo : fooCollection)为空,则会获得NPE。
  2. 自动取消装箱号码:fooCollection
  3. 一般来说,您需要了解NPE的调试,当然还有更一般的建议,您应该记录变量值或使用调试器逐步执行代码。