Reputation: 175
I have a JTable and I am trying to add a header tool tip that will display the string that is in the table header for each of the header cells. I can set the value of the header cell:
colModel.getColumn(currentColumn).setHeaderValue(time + "(s)");
where colModel:
TableColumnModel colModel = audioTable.getColumnModel();
To do this, I've added this listener:
audioTable = new JTable(modelAudio);
JTableHeader header = audioTable.getTableHeader();
header.addMouseMotionListener(new MouseMotionListener() {
@Override
public void mouseMoved(MouseEvent e) {
System.out.println("mouseMoved");
// TODO Auto-generated method stub
}
@Override
public void mouseDragged(MouseEvent e) {
System.out.println("mouseDragged");
// TODO Auto-generated method stub
}
});
And I see mouseMoved
being printed over and over again in between this NPE:
Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
at javax.swing.plaf.synth.SynthTableHeaderUI$HeaderRenderer.getTableCellRendererComponent(Unknown Source)
at javax.swing.table.JTableHeader.getToolTipText(Unknown Source)
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$400(Unknown Source)
at java.awt.EventQueue$2.run(Unknown Source)
at java.awt.EventQueue$2.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.AccessControlContext$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)
I'm not sure how to get a longer stack trace, this is how I created the table:
modelAudio = new DefaultTableModel();
modelAudio.addColumn(" ");
audioTable = new JTable(modelAudio);
The tricky thing i am trying to do is to add column's dynamically, so i add a column each time the user populates the current column like so:
TableColumn tc = new TableColumn(modelAudio.getColumnCount());
tc.setHeaderValue(" ");
audioTable.addColumn(tc);
modelAudio.addColumn(tc);
Is the way that I am adding the columns the problem causing this NPE?
Upvotes: 1
Views: 1116
Reputation: 32323
First of all, you haven't included enough code for me to figure out why the NullPointerException
, but fortunately that's okay because you're approaching the problem the wrong way.
You don't need to use a MouseMotionListener
at all. Swing already supports a ToolTip
behavior, all you need to do is get access to the cell renderer itself. Simply set the renderer to a value that will set the ToolTipText
property before rendering the component.
You haven't included enough code for me to show you how to do this in your app, but I can show you how to do it in the tutorial app from Oracle: In the initial setup, do this:
final TableCellRenderer renderer = table.getDefaultRenderer(Object.class);
table.setDefaultRenderer(Object.class, new TableCellRenderer() {
@Override
public Component getTableCellRendererComponent(JTable table,
Object value, boolean isSelected, boolean hasFocus, int row,
int column) {
Component component = renderer.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
String columnHeader = table.getColumnModel().getColumn(column).getHeaderValue().toString();
((JComponent) component).setToolTipText(columnHeader);
return component;
}
});
Here's the complete code of the demo with some of the unneeded code stripped out:
import javax.swing.*;
import javax.swing.table.TableCellRenderer;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.GridLayout;
public class SimpleTableDemo extends JPanel {
public SimpleTableDemo() {
super(new GridLayout(1, 0));
String[] columnNames = { "First Name", "Last Name", "Sport", "# of Years",
"Vegetarian" };
Object[][] data = {
{ "Kathy", "Smith", "Snowboarding", new Integer(5), new Boolean(false) },
{ "John", "Doe", "Rowing", new Integer(3), new Boolean(true) },
{ "Sue", "Black", "Knitting", new Integer(2), new Boolean(false) },
{ "Jane", "White", "Speed reading", new Integer(20), new Boolean(true) },
{ "Joe", "Brown", "Pool", new Integer(10), new Boolean(false) } };
final JTable table = new JTable(data, columnNames);
table.setPreferredScrollableViewportSize(new Dimension(500, 70));
table.setFillsViewportHeight(true);
final TableCellRenderer renderer = table.getDefaultRenderer(Object.class);
table.setDefaultRenderer(Object.class, new TableCellRenderer() {
@Override
public Component getTableCellRendererComponent(JTable table,
Object value, boolean isSelected, boolean hasFocus, int row,
int column) {
Component component = renderer.getTableCellRendererComponent(table,
value, isSelected, hasFocus, row, column);
String columnHeader = table.getColumnModel().getColumn(column)
.getHeaderValue().toString();
((JComponent) component).setToolTipText(columnHeader);
return component;
}
});
// Create the scroll pane and add the table to it.
JScrollPane scrollPane = new JScrollPane(table);
// Add the scroll pane to this panel.
add(scrollPane);
}
private static void createAndShowGUI() {
// Create and set up the window.
JFrame frame = new JFrame("SimpleTableDemo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// Create and set up the content pane.
SimpleTableDemo newContentPane = new SimpleTableDemo();
newContentPane.setOpaque(true); // content panes must be opaque
frame.setContentPane(newContentPane);
// Display the window.
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
// Schedule a job for the event-dispatching thread:
// creating and showing this application's GUI.
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
}
And a screenshot (obviously my mouse isn't captured in the screenshot):
You can do something similar for the ColumnHeader
, by using table.getTableHeader().getDefaultRenderer()
:
final TableCellRenderer header = table.getTableHeader().getDefaultRenderer();
table.getTableHeader().setDefaultRenderer(new TableCellRenderer() {
@Override
public Component getTableCellRendererComponent(JTable table,
Object value, boolean isSelected, boolean hasFocus, int row,
int column) {
Component tableCellRendererComponent = header.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
String columnHeader = table.getColumnModel().getColumn(column)
.getHeaderValue().toString();
((JComponent) tableCellRendererComponent).setToolTipText(columnHeader);
return tableCellRendererComponent;
}
});
Upvotes: 2