Custom Java tool tip with Swing components as cont

2019-01-17 22:13发布

I'm trying to show multiple images in a component's tooltip, found createToolTip() and implemented a custom that adds the needed components like this:

setComponent(component);

JPanel images = new JPanel(null);
images.setLayout(new BoxLayout(images, BoxLayout.X_AXIS));
for(ImageIcon icon:myIcons) {
    images.add(new JLabel(icon));
}

JPanel content = new JPanel(new BorderLayout());
content.add(new JLabel(title), BorderLayout.NORTH);
content.add(new JLabel(description));
content.add(images, BorderLayout.SOUTH);

add(content);

However, all I see is a little dot, indicating that the tool tip is shown, but somehow the size is ignored. What do I miss implementing a custom tooltip?

6条回答
冷血范
2楼-- · 2019-01-17 22:50

I'd suggest to using JWindow or un_decorated JDialog, as popup window (used by default for JCalendar or JDatePicker) rather than JTooltip, for nicer output to the GUI implements Translucent and Shaped Windows

查看更多
smile是对你的礼貌
3楼-- · 2019-01-17 22:50

Instead of reinventing the wheel try this: https://github.com/timmolderez/balloontip. You can put any content as JComponent.

查看更多
兄弟一词,经得起流年.
4楼-- · 2019-01-17 22:52

The base "problems" are that JToolTip

  • is-not designed as a container, it's only accidentally a container because JComponent is. For a Swing "not-container" its the responsibility of the ui-delegate to act as LayoutManager.
  • isn't rich enough, it can handle text-only (at least with the emergency door html, which is @Andrew's favourite :-)

By-passing those limitations basically is a driving that widget nearly over the edge. A clean solution would roll a new component .. On the other hand, the OP already found the screws to tweak. The only thingy that could be slightly improved is to neither call setXXSize, nor set a custom ui. Instead, make it behave like a container by overriding getXXSize() like:

@Override
public Dimension getPreferredSize() {
    if (getLayout() != null) {
        return getLayout().preferredLayoutSize(this);
    }
    return super.getPreferredSize();
}
查看更多
Root(大扎)
5楼-- · 2019-01-17 22:58

It might sound silly but, have you tried setting bounds for JPanel ?

setBounds(100, 100, 150, 50);

And you can try setting a gap between components in BorderLayout

JPanel content = new JPanel(new BorderLayout(1,1));
查看更多
smile是对你的礼貌
6楼-- · 2019-01-17 22:58

There are essentially two things missing. First of all, JToolTip extends JComponent, and unlike JPanel, it doesn't have a default layout. To stretch the content across the tooltip, use a BorderLayout.

setLayout(new BorderLayout());

The second problem is the size. The ToolTipManager respects the preferred size of the tool tip. While the BorderLayout calculates the size, the ToolTipUI ignores it. So, there are two alternatives: Manually set the preferred size...

setPreferredSize(content.getPreferredSize());

Note that this does not make the layout obsolete; otherwise, you get an empty tool tip with the right size.

... or subclass ToolTipUI to respect the layout, which is what I went with. The resulting code is:

setComponent(StadtLabel.this);

JPanel images = new JPanel(null);
waren.setLayout(new BoxLayout(waren, BoxLayout.X_AXIS));
for(ImageIcon icon:myIcons) {
    JLabel lbl = new JLabel(icon);
}

JPanel content = new JPanel(new BorderLayout());
content.add(new JLabel(title), BorderLayout.NORTH);
content.add(new JLabel(description));
content.add(images, BorderLayout.SOUTH);

setLayout(new BorderLayout());
add(content);
setUI(new ToolTipUI() {
    @Override
    public Dimension getMinimumSize(JComponent c) {
        return c.getLayout().minimumLayoutSize(c);
    }

    @Override
    public Dimension getPreferredSize(JComponent c) {
        return c.getLayout().preferredLayoutSize(c);
    }

    @Override
    public Dimension getMaximumSize(JComponent c) {
        return getPreferredSize(c);
    }
});
查看更多
乱世女痞
7楼-- · 2019-01-17 23:08

Tool tips can render HTML. If you can form URLs to the images (not practical if they are generated in memory but usually doable otherwise), it is an easy matter to write some HTML that will load the images, and use that HTML as the tool tip.


E.G.

MultiIconToolTip

import javax.swing.*;

class MultiIconToolTip {

    public static void main(String[] args) throws Exception {
        final String html =
            "<html><body>" +
            "<img src='" +
            "http://i.stack.imgur.com/OVOg3.jpg" +
            "' width=160 height=120> " +
            "<img src='" +
            "http://i.stack.imgur.com/lxthA.jpg" +
            "' width=160 height=120>" +
            "<p>Look Ma, no hands!";
        SwingUtilities.invokeLater( new Runnable() {
            public void run() {
                JLabel hover = new JLabel("Point at me!");
                hover.setToolTipText(html);
                JOptionPane.showMessageDialog(null, hover);
            }
        });
    }
}
查看更多
登录 后发表回答