Hej,

Obsadzam moją JTable danymi pobieranymi z bazy danych MySQL. Tworzę w tym celu "DefaultTableModel dtm". Pobieram następnie informacje o wierszach i kolumnach z bazy danych. W ten sposób "dtm" zawiera niezbędne wszystkie informacje o danych zawartych w bazie danych. Następnie ustawiam JTable.setModel(dtm).

Teraz chcę dodać do jtableheader'a w kolejnych kolumnach ToolTipy. Tworzę więc nowy obiekt klasy ToolTipHeader, która dziedziczy po JTableHeader. Jako parametr do konstruktora obiektu tej klasy wysyłam "String[]" z tekstami na tooltipy. W klasie ToolTipHeader powstaje customowy header reagujący na akcję myszy. Jeżeli najadę na dany nagłówek, to powinien pojawić się tooltip.

Problem pojawia się, gdy próbuję dodać taki header do mojej tabeli. Gdy próbuję wykonać JTable.setTableHeader(obiekt ToolTipHeader), to kompilator wywala mi "NullPointerException". Nie mam pojęcia dlaczego. Klasa ToolTipHeader wydaje się nienaganna. Poza tym JTable posiada JColumnModel. Dodawałem przecież m.in. do "dtm" "setColumnIdentifiers" pobierane z bazy danych SQL. Poza tym testy z użyciem konsoli też "mówią", że columnmodel istnieje :P

Będę bardzo wdzięczny za pomoc. Poniżej zamieszczam kawałek kodu obsadzającego JTable i klasę od Headera.

/*
 * Kod Zaludniający Tabelę
 */
...
String sql = "SELECT * FROM " + dbCombo.getSelectedItem().toString() + " ORDER BY SessionID DESC";
try {
     ps = conn.prepareStatement(sql);
     rs = ps.executeQuery();
     ResultSetMetaData rsmetadata = rs.getMetaData();
     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);
     TTHeader tth = new TTHeader(table.getColumnModel());
     tth.setToolTipStrings(tooltipsSDB);
     table.setTableHeader(tth); // Na tej linii kodu wywala NullPointerException (z dopiskiem "Unknown Source")
     table.repaint();
} catch (SQLException e) {
     JOptionPane.showMessageDialog(null, "Populate table error! \n" + e);
} 
...

/*
 * Klasa Tworzącą Customowy Nagłówek
 */
class TTHeader extends JTableHeader {
     
     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;
     }
}

EDIT

Problem rozwiązany. Pomogła inicjalizacja tabeli przy każdorazowej zmianie bazy danych, która miałaby być wyświetlana w owej tabeli. Wyjątek zgłaszała linijka " int modelCol = getTable().convertColumnIndexToModel(col);" przy zmianach bazy danych. Nie rozumiem jednak do końca dlaczego. Metoda populateTable() przecież rebuduje tabelę na podstawie pobranych danych od nowa - dlaczego więc metoda getModel() zgłaszała NPE mimo istnienia już owej tabeli?

Pozdrawiam serdecznie.