0

我尝试将工具提示添加到我的 JTable 标题中。在这种情况下,我使用扩展 JTableHeader Java 类的 TTHeader 类。一切似乎都很好,但是当我尝试将新的 TTHeader 标头添加到我的 JTable 时,我得到了带有 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);
4

1 回答 1

1

当您获得 NPE 并识别出该行时,您检查的第一件事是所有出现的取消引用运算符 ( .)。这种运算符左侧(!)的值将是null。(如果你.在一行上有多个 s ,那么其中之一。所以如果你的行是foo.getBar().doSomething(),要么fooisnull要么foo.getBar()返回null。但是doSomething()返回什么并不重要。)

在这种情况下,它可能是getTable()返回的方法null

自 Java 5 以来,出现了两个新的、相当隐蔽的 NPE 可能原因:

  1. 中的隐式取消引用,如果为空,您将在for (Foo foo : fooCollection)此处获得 NPE 。fooCollection
  2. 数字自动拆箱:Integer i = null; int j = i + 1; //NPE here

这就是您需要了解的有关 NPE 调试的全部信息,当然还有更一般的建议,即您应该记录变量值或使用调试器逐步执行代码。

于 2013-09-24T16:45:36.493 回答