Joseph
Joseph

Reputation: 171

Force a Java Tooltip to Appear

Given a JTextField (or any JComponent for that matter), how would one go about forcing that component's designated tooltip to appear, without any direct input event from the user? In other words, why is there no JComponent.setTooltipVisible(boolean)?

Upvotes: 17

Views: 16847

Answers (5)

bench_doos
bench_doos

Reputation: 169

It's not a ToolTip, but you can use a balloon tip: http://timmolderez.be/balloontip/doku.php

It is showing just on call and feels better in some moments then Default ToolTip

Upvotes: 0

Jan Trembulak
Jan Trembulak

Reputation: 21

For me works the similar version stated above (instead of Timer I used SwingUtilities and invokeLater approach):

private void showTooltip(Component component)
{
    final ToolTipManager ttm = ToolTipManager.sharedInstance();
    final int oldDelay = ttm.getInitialDelay();
    ttm.setInitialDelay(0);
    ttm.mouseMoved(new MouseEvent(component, 0, 0, 0,
            0, 0, // X-Y of the mouse for the tool tip
            0, false));
    SwingUtilities.invokeLater(new Runnable()
    {
        @Override
        public void run() 
        {
            ttm.setInitialDelay(oldDelay);
        }
    });
}

Upvotes: 2

Olivier Faucheux
Olivier Faucheux

Reputation: 2606

You can access the ToolTipManager, set the initial delay to 0 and send it an event. Don't forget to restore the values afterwards.

private void displayToolTip()
{
    final ToolTipManager ttm = ToolTipManager.sharedInstance();
    final MouseEvent event = new MouseEvent(this, 0, 0, 0,
                                            0, 0, // X-Y of the mouse for the tool tip
                                            0, false);
    final int oldDelay = ttm.getInitialDelay();
    final String oldText = textPane.getToolTipText(event);
    textPane.setToolTipText("<html><a href='http://www.google.com'>google</a></html>!");
    ttm.setInitialDelay(0);
    ttm.setDismissDelay(1000);
    ttm.mouseMoved(event);

    new Timer().schedule(new TimerTask()
    {
        @Override
        public void run()
        {
            ttm.setInitialDelay(oldDelay);
            textPane.setToolTipText(oldText);
        }
    }, ttm.getDismissDelay());
}

Upvotes: 0

camickr
camickr

Reputation: 324118

You need to invoke the default Action to show the tooltip. For example to show a tooltip when a component gains focus you can add the following FocusListener to the component:

FocusAdapter focusAdapter = new FocusAdapter()
{
    public void focusGained(FocusEvent e)
    {
        JComponent component = (JComponent)e.getSource();
        Action toolTipAction = component.getActionMap().get("postTip");

        if (toolTipAction != null)
        {
            ActionEvent postTip = new ActionEvent(component, ActionEvent.ACTION_PERFORMED, "");
            toolTipAction.actionPerformed( postTip );
        }

    }
};

Edit:

The above code doesn't seem to work anymore. Another approach is dispatch a MouseEvent to the component:

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

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

                MouseEvent phantom = new MouseEvent(
                    component,
                    MouseEvent.MOUSE_MOVED,
                    System.currentTimeMillis(),
                    0,
                    10,
                    10,
                    0,
                    false);

                ToolTipManager.sharedInstance().mouseMoved(phantom);
            }
        };

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

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

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

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

    public static void main(String[] args)
    {
        EventQueue.invokeLater(new Runnable()
        {
            public void run()
            {
                createAndShowUI();
            }
        });
    }
}

This approach will result in a slight delay before the tooltip is displayed as it simulated the mouse entering the component. For immediate display of the tooltip you can use pstanton's solution.

Upvotes: 5

pstanton
pstanton

Reputation: 36640

The only way (besides creating your own Tooltip window) I've found is to emmulate the CTRL+F1 keystroke on focus:

new FocusAdapter()
{
    @Override
    public void focusGained(FocusEvent e)
    {
        try
        {
            KeyEvent ke = new KeyEvent(e.getComponent(), KeyEvent.KEY_PRESSED,
                    System.currentTimeMillis(), InputEvent.CTRL_MASK,
                    KeyEvent.VK_F1, KeyEvent.CHAR_UNDEFINED);
            e.getComponent().dispatchEvent(ke);
        }
        catch (Throwable e1)
        {e1.printStackTrace();}
    }
}

Unfortunately, the tooltip will disappear as soon as you move your mouse (outside of the component) or after a delay (see ToolTipManager.setDismissDelay).

Upvotes: 6

Related Questions