JTableHeader not resetting to the new JTableHeader/dataModel

60 Views Asked by At

I have a weird bug.

I have a frame that initializes with an empty table, table = JTable(new DefaultTableModel()). When the user selects a file, the table get filled with table.setModel(DefaultTableModel(data,header));

Everything displays correctly, my tooltips over the cells show correctly. The header has a shortened date format e.g. "26/3", "27/3", etc. this helps keep the columns thin. I would like the tooltip to show a human readable date format "Sunday, 26/March/2023".

After setting the new data to the table. I set the table to the new header, table.setTableHeader(new CustomTableHeader(table.getColumnModel(),header)); but it does not take into affect, the mouseMoved does not trigger when the mouse hovers over the header,

If I set the tableheader in the initialize stage (By un-commenting line 44), the mouseMoved does trigger when the mouse hovers over the header, but does not take new tooltip array.

I would like for the setTableHeader to take into affect after the user reads a file and for the tooltips to show when the mouse hovers the table header with the corresponding tooltip.

Below is the example code.

import javax.swing.*;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.JTableHeader;
import javax.swing.table.TableColumnModel;

import java.awt.*;
import java.awt.event.*;
import java.util.Vector;

public class JTableExample extends JFrame implements ActionListener {
  private JTable table;
  public JTableExample(){
    setLayout(new BorderLayout());
    add(mainPanel(),BorderLayout.CENTER);
    add(bottomPanel(),BorderLayout.SOUTH);

    setTitle("JTableExample");
    setSize(600,300);
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    setLocationRelativeTo(null);
    setVisible(true);
  }

  private JScrollPane mainPanel(){
    table = new JTable(new DefaultTableModel()){
        @Override
        public String getToolTipText(MouseEvent e) {
          String tip = null;
          Point p = e.getPoint();
          int rowIndex = rowAtPoint(p);
          int colIndex = columnAtPoint(p);

          if (rowIndex >= 0 && colIndex >= 0) {
                tip = getValueAt(rowIndex, colIndex).toString();
          }

        return tip;
        }

      };

    //table.setTableHeader(new CustomTableHeader(table.getColumnModel(), new String[0]));

    return new JScrollPane(table);
  }

  private JPanel bottomPanel(){
    JPanel panel = new JPanel();

    JButton btnReadFile = new JButton("Read File");
    btnReadFile.setActionCommand("readFile");
    btnReadFile.addActionListener(this);

    panel.add(btnReadFile);

    return panel;
  }

  public void actionPerformed(ActionEvent ae) {
    if(ae.getActionCommand().equals("readFile")){
      Vector<Vector<String>> data = new Vector<>();
      Vector<String> header = new Vector<>();

      Vector<String> row = new Vector<>();

      for(int i = 0;i<3;i++){
        row.add(String.valueOf(i));
        header.add("column " + i);
      }

      data.add(row);
      row = new Vector<>();

      for(int i = 3;i<6;i++){
        row.add(String.valueOf(i));
      }

      data.add(row);

      table.setModel(new DefaultTableModel(data,header));
      table.setTableHeader(new CustomTableHeader(table.getColumnModel(), header.toArray(new String[header.size()])));
    }

  }

  class CustomTableHeader extends JTableHeader {
    public CustomTableHeader(TableColumnModel columnModel, String[] tooltips) {
      super(columnModel);
      System.out.println("CustomTableHeader initialized...");

        // print out the tooltips for testing...
        for(String col : tooltips){
          System.out.println(col);
        }

        addMouseMotionListener(new MouseMotionAdapter() {
            @Override
            public void mouseMoved(MouseEvent e) {
              System.out.println("mouse entered...");
              int column = columnModel.getColumnIndexAtX(e.getX());
              System.out.println("column=" + column);

                if (column >= 0 && column < tooltips.length) {
                  setToolTipText(tooltips[column]);
                }
            }
          });
    }
  }

  public static void main(String[] args){
    new JTableExample();
  }
}

Any help will be greatly appreciated.

1

There are 1 best solutions below

3
On
table.setModel(new DefaultTableModel(data,header));
table.setTableHeader(new CustomTableHeader(...) );

The problem is you reset the header of the table, but header has not been replaced as the row header of the scroll pane.

Refactor the code to reset the view of the scroll pane:

table.setModel(new DefaultTableModel(data,header));
table.setTableHeader(new CustomTableHeader(...) );
scrollPane.setViewportView( table );

This will now update the row header of the scroll pane.

You may also want to check out the section from the Swing tutorial on Specifying Tooltips For Column Headers which suggests you override the getToolTipText(...) method. No need for a MouseListener.