Given a JTextField
(or any JComponent
for that matter), how would one go about forcing that component\'s designated tooltip to appear, without any
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
).
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
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);
}
});
}
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.
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());
}