JToolTip Behavior Outside JFrames

As I was working on a small application, I started implementing a custom JToolTip to be used throughout the app, in stead of Swing’s default JToolTip.

The custom JToolTip entirely inside the JFrame.
The custom tooltip entirely inside the JFrame.

Testing the application I was surprised by the behavior of the tooltips when they would exceed the borders of a JFrame (exceeding for a pixel was enough).

In the image below, you can notice that a background (default Swing Color) is present for the tooltip component. This background was not present for the exact same tooltip if it appeared inside the frame. So, the goal was to remove this background.

The custom JToolTip exceeding the JFrame's border.
The custom tooltip exceeding the JFrame’s border.

First thing that came in mind was, ‘I should change the background to a transparent one’. And so I did, by calling this line on the JToolTip (mind the last parameter, the alpha value of the color):

setBackground(new Color(255, 255, 255, 0));<br />

Obviously that didn’t do the trick, but it was one step closer to the solution. In fact, someone pointed out that when the component surpasses the frame’s borders, it is actually added to a JWindow prior to being displayed.

SwingUtilities provides a method that returns the Window of a specified component:

SwingUtilities.windowForComponent(...);

It sufficed to update the background color of the window, in which the tooltip was housed, with a transparent one (alpha value of 0).

As an additional measure I made sure all the parent components of the tooltip were set to be non-opaque.

The final solution could be implemented in the overridden addNotify() method:

@Override
    public void addNotify() {
        super.addNotify();
        setOpaque(false);
        Component parent = this.getParent();
        if (parent != null) {
            if (parent instanceof JComponent) {
                JComponent jparent = (JComponent) parent;
                jparent.setOpaque(false);
            }
        }
        Window window = SwingUtilities.windowForComponent(this);
        try {
            window.setBackground(new Color(255, 255, 255, 0));
        } catch (IllegalComponentStateException e) {
            //Do nothing
        }
    }

In the above code, you may notice the catch block handling potentially raised exception: IllegalComponentStateException. It was vital to add that catch statement in. A tooltip inside a frame, not exceeding the borders, is not added to a JWindow before being displayed. This means no window background should be changed, as there would be no window.

Find the question on StackOverflow for further reference.

Author: Thibault Helsmoortel

Belgian IT enthusiast with a wide range of interests. Enjoys table tennis and meeting friends at the local bar.

Leave a Reply