tags:

views:

94

answers:

3

I have a component where i want to display a custom jtooltip. That is easy, just change the getTooltip method. Similar for location and text.

However i also want to change the timers. The tooltip should always be displayed if the mouse is over a cellrenderer of the component. If it leaves all of those it should be turned invisible. I know that i can use TooltipManager to control the times globally. But the best solution is probably to just shortcircut that and display the tooltip myself with a mouselistener. However when i tried to do that (unregister the component in TooltipManager and setting the tooltip visible, with text and in the correct position, in a mouse listener) the tooltip never showed at all. What am i doing wrong?

Edit: Now the question has changed! Into 2 questions.

My solution is for now this, however it losses the shadow that the jtooltip always displays sometimes frustratingly, and it is hidden if the mouse exits into the popup itself. How to filter the mouseexit events over the popup if the popup is not even a component? I could do some hacking based on the lastPosition, but that seems stupid, since i don't really know its width.

    private Popup lastPopup;
    private final JToolTip tooltip = ...;
    private Point lastPoint;
   @Override public void mouseMoved(MouseEvent e) {
        Point p = privateToolTipLocation(e);
        if (p == null || p.equals(lastPoint)) {
            return;
        }
        lastPoint = p;
        tooltip.setTipText(privateToolTipText(e));
        //copy
        p = new Point(p);
        SwingUtilities.convertPointToScreen(p, this);
        Popup newPopup = PopupFactory.getSharedInstance().getPopup(this, tooltip, p.x, p.y);
        if (lastPopup != null) {
            lastPopup.hide();
        }
        lastPopup = newPopup;
        newPopup.show();
    }

    @Override public void mouseExited(MouseEvent e) {
        if (lastPopup != null && someUnknownCondiction) {
            lastPopup.hide();
            lastPopup = null;
        }
    }
A: 

Apparently what controls the display of the Tooltip is if the getTooltipText returns null or not. Having that to null, eliminated a npe and allowed things to display. However there are some artifacts still..

i30817
+1  A: 

But the best solution is probably to just shortcircut that and display the tooltip myself with a mouselistener

Invoke the default Action for the component to display the tooltip:

Action toolTipAction = component.getActionMap().get("postTip");

if (toolTipAction != null)
{
    ActionEvent postTip = new ActionEvent(component, ActionEvent.ACTION_PERFORMED, "");
    toolTipAction.actionPerformed( postTip );
}
camickr
+1  A: 

Rather than trying to reimplement the display of tooltips, you could add a mouse listener to your component that changes the global tooltip timer when the mouse enters and leaves the region above the component.

Here is some example code:

instantTooltipComponent.addMouseListener(new MouseAdapter() 
{    
    final int defaultTimeout = ToolTipManager.sharedInstance().getInitialDelay();

    @Override
    public void mouseEntered(MouseEvent e) {
        ToolTipManager.sharedInstance().setInitialDelay(0);
    }

    @Override
    public void mouseExited(MouseEvent e) {
        ToolTipManager.sharedInstance().setInitialDelay(defaultTimeout);
    }
});

This should change the tooltip delay to zero whenever the mouse moves over your component and change it back to the default delay whenever the mouse moves off of your component.

Joe Carnahan
I guess that works. Dirty but works, since there can't be two mouse pointers. Ok. You're marked correct.
i30817
One of the deeper mysteries of programming is the question, "When is 'dirty but works' actually OK?" ;-)
Joe Carnahan
When the app is small and simple. With larger apps these sort of hacks can start to mount up and cause all sorts of issues.
Keilly
Also with odd hacks (in the nicest sense of the word) unexpected situations can occur, in this example if the user puts the mouse over the component then changes the focus to another app (say via alt-tab) then the mouse exited event won't post until the app regains focus. May or may not give you what you want - who knows?
Keilly