Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to change the jtooltip timers for 1 component

Tags:

java

swing

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;
        }
    }
like image 979
i30817 Avatar asked Dec 22 '22 04:12

i30817


2 Answers

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.

like image 200
Joe Carnahan Avatar answered Jan 09 '23 01:01

Joe Carnahan


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 );
}

Edit:

Above code doesn't appear to work anymore. Ctrl+F1 is the default KeyStroke used to display the tool tip of a component. So an alternative approach is to dispatch the Ctrl+F1 KeyStroke to the component. For example:

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class PostTipSSCCE2 extends JPanel
{
    public PostTipSSCCE2()
    {
        FocusAdapter fa = new FocusAdapter()
        {
            public void focusGained(FocusEvent e)
            {
                JComponent component = (JComponent)e.getSource();

                KeyEvent ke = new KeyEvent(
                    component,
                    KeyEvent.KEY_PRESSED,
                    System.currentTimeMillis(),
                    KeyEvent.CTRL_MASK,
                    KeyEvent.VK_F1,
                    KeyEvent.CHAR_UNDEFINED);

                component.dispatchEvent( ke );
            }
        };

        MouseAdapter ma = new MouseAdapter()
        {
            @Override
            public void mouseEntered(MouseEvent e)
            {
                JComponent component = (JComponent)e.getSource();

                KeyEvent ke = new KeyEvent(
                    component,
                    KeyEvent.KEY_PRESSED,
                    System.currentTimeMillis(),
                    KeyEvent.CTRL_MASK,
                    KeyEvent.VK_F1,
                    KeyEvent.CHAR_UNDEFINED);

                component.dispatchEvent( ke );
            }
        };

        JButton button = new JButton("Button");
        button.setToolTipText("button tool tip");
        button.addFocusListener( fa );
        button.addMouseListener( ma );
        add( button );

        JTextField textField = new JTextField(10);
        textField.setToolTipText("text field tool tip");
        textField.addFocusListener( fa );
        textField.addMouseListener( ma );
        add( textField );

        JCheckBox checkBox =  new JCheckBox("CheckBox");
        checkBox.setToolTipText("checkbox tool tip");
        checkBox.addFocusListener( fa );
        checkBox.addMouseListener( ma );
        add( checkBox );
    }

    private static void createAndShowUI()
    {
        JFrame frame = new JFrame("PostTipSSCCE2");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add( new JScrollPane(new PostTipSSCCE2()) );
        frame.pack();
        frame.setLocationByPlatform( true );
        frame.setVisible( true );
    }

    public static void main(String[] args)
    {
        EventQueue.invokeLater(new Runnable()
        {
            public void run()
            {
                createAndShowUI();
            }
        });
    }
}
like image 40
camickr Avatar answered Jan 09 '23 02:01

camickr