Reputation: 378
I am working on a dictionary app that displays word entries like this:
The word entry is made up of five JLabels. The JLabels EN, n and the star have tooltip text that explains what the abbreviation or symbol means. This works correctly when the word entry is placed in a regular JPanel, but if it is placed in a JList item the tooltip text is not displayed- presumably overwritten by the JList's (non-existent) tooltip.
I have seen answers like this, but they only add a tooltip for the JList item, not for individual JComponents with the item.
Is there any way to, for example, change the Z-order so that the tooltips for the JLabels is visible?
Upvotes: 0
Views: 345
Reputation: 324128
The word entry is made up of five JLabels.
You should NOT be storing Swing compnents in the ListModel. The point of using renderers is to store the data in the model and then use a renderer to display the data.
So in your case you need to create a custom object with 8 properties. 5 properties for the text to be displayed in the labels and 3 properties for the tooltip text. Then your renderer will be a JPanel with 5 labels. In the rendering code you simply set the text of each of the 5 labels with the data from your custom object. You would also set the tooltip text.
Next you will need to override the getToolTipText(MouseEvent)
method of the JList. The default implementation of this code gets the renderer and then just returns the tootip of the renderer. This is simple because the renderer is usually just a single JLabel.
In your case the logic will be slightly more complicated because you have child components in the renderer so you will need to get the tooltip of the child component.
Following is the current code from the getToolTipText(...)
method:
public String getToolTipText(MouseEvent event) {
if(event != null) {
Point p = event.getPoint();
int index = locationToIndex(p);
ListCellRenderer<? super E> r = getCellRenderer();
Rectangle cellBounds;
if (index != -1 && r != null && (cellBounds =
getCellBounds(index, index)) != null &&
cellBounds.contains(p.x, p.y)) {
ListSelectionModel lsm = getSelectionModel();
Component rComponent = r.getListCellRendererComponent(
this, getModel().getElementAt(index), index,
lsm.isSelectedIndex(index),
(hasFocus() && (lsm.getLeadSelectionIndex() ==
index)));
if(rComponent instanceof JComponent) {
MouseEvent newEvent;
p.translate(-cellBounds.x, -cellBounds.y);
newEvent = new MouseEvent(rComponent, event.getID(),
event.getWhen(),
event.getModifiers(),
p.x, p.y,
event.getXOnScreen(),
event.getYOnScreen(),
event.getClickCount(),
event.isPopupTrigger(),
MouseEvent.NOBUTTON);
String tip = ((JComponent)rComponent).getToolTipText(
newEvent);
if (tip != null) {
return tip;
}
}
}
}
return super.getToolTipText();
}
I thank the code you need to change would be in this area:
p.translate(-cellBounds.x, -cellBounds.y);
newEvent = new MouseEvent(rComponent, event.getID(),
This translates the mouse point from the JList to the renderer. So now I think you just need to modify the logic to get the label at the translated point and then get the labels tool tip.
So the new code might be something like:
p.translate(-cellBounds.x, -cellBounds.y);
Component label = rComponent.getComponentAt(p);
if (label == null) return super.getToolTipText();
newEvent = new MouseEvent(label, event.getID(),
Upvotes: 2
Reputation: 35021
You are confused. You don't add Components to a JList, you use a ListRenderer.
So you have two choices: You can either build your own custom tooltip for the JList, or create your own version of JList
Upvotes: 1