ideyedi
ideyedi

Reputation: 11

Tooltip to show a keystroke in java

Pressing the Control key I want to show a Jtooltip of a Jbutton.

How can I show a tooltip to the desired keystrokes?

Upvotes: 0

Views: 842

Answers (2)

MadProgrammer
MadProgrammer

Reputation: 347244

There is a private method in the TooltipManager called show which takes a JComponent as a parameter, which is used to show the tooltip. This is actually used by the TooltipManager when CTRL+F1 is pressed...

So, my first recommendation would be, use CTRL+F1 because it's built in. My second recommendation is to use CTRL+F1 because people press CTRL for a lot of reasons (like copy/paste, menu short cuts, etc), which could be rather annoying if you keep popping up tool tips all the time. My third recommendation is to use CTRL+F1 because the show method is private

However, because I'm simply curious (and completely crazy), you "could" (but I wouldn't recommend it) use a dirty, dirty hack (I fell like Phillip Fry), which is just as likely to blow up in your face as solve the problem (but I was curious about how to bind an action to the CTRL key)

import java.awt.Component;
import java.awt.EventQueue;
import java.awt.KeyboardFocusManager;
import java.awt.event.ActionEvent;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.ActionMap;
import javax.swing.InputMap;
import javax.swing.JButton;
import javax.swing.JComponent;
import static javax.swing.JComponent.WHEN_IN_FOCUSED_WINDOW;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import javax.swing.ToolTipManager;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class Test {

    public static void main(String[] args) {
        new Test();
    }

    public Test() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        public TestPane() {
            JButton btn = new JButton("Banana");
            btn.setToolTipText("Hello");
            add(btn);
            TooltipPopup.register(this);
        }

    }

    public static class TooltipPopup {

        public static void register(JComponent comp) {
            new TooltipPopup(comp);
        }

        private JComponent parent;
        private boolean showing = false;

        private TooltipPopup(JComponent parent) {
            this.parent = parent;
            bindKeyStrokeTo(parent,
                            JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT,
                            "help.press",
                            KeyStroke.getKeyStroke(KeyEvent.VK_CONTROL, InputEvent.CTRL_DOWN_MASK),
                            new AbstractAction() {
                                @Override
                                public void actionPerformed(ActionEvent e) {
                                    if (!showing) {
                                        Component comp = KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner();
                                        if (comp != null && comp instanceof JComponent) {
                                            JComponent focused = (JComponent) comp;
                                            try {
                                                Class clazz = ToolTipManager.sharedInstance().getClass();
                                                Method method = clazz.getDeclaredMethod("show", JComponent.class);
                                                method.setAccessible(true);
                                                method.invoke(ToolTipManager.sharedInstance(), focused);
                                                showing = true;
                                            } catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) {
                                                ex.printStackTrace();
                                            }
                                        }
                                    }
                                }
                            });
            bindKeyStrokeTo(parent,
                            JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT,
                            "help.release",
                            KeyStroke.getKeyStroke(KeyEvent.VK_CONTROL, 0, true),
                            new AbstractAction() {
                                @Override
                                public void actionPerformed(ActionEvent e) {
                                    showing = false;
                                }
                            });
        }

        public void bindKeyStrokeTo(JComponent parent, int condition, String name, KeyStroke keyStroke, Action action) {
            InputMap im = parent.getInputMap(condition);
            ActionMap am = parent.getActionMap();

            im.put(keyStroke, name);
            am.put(name, action);
        }

    }

}

All this does is binds a press and release Action to the CTRL for a given component (parent container), which will find the currently focused component and show it's tool tip.

It uses a reflection "tick" (hack) to call the private show method of the ToolTipManager.

You need the "press" and "release" actions, because otherwise you will get a repeated key event, which will make the tool tip "flash"

camickr solution is the better (and correct) choice, this was a simply "I wonder how" hack

Upvotes: 1

camickr
camickr

Reputation: 324128

Not sure if I understand the question, but you can use Control+F1 to display the tooltip of the currently focused component.

Upvotes: 2

Related Questions