Multi-line tooltips in Java?

前端 未结 10 1564
故里飘歌
故里飘歌 2020-12-02 12:31

I\'m trying to display tooltips in Java which may or may not be paragraph-length. How can I word-wrap long tooltips?

相关标签:
10条回答
  • 2020-12-02 13:11

    I know this one is quite old but i found a quite simple solution using HTML code!

    Just use a HTML Paragraph with a fixed width:

    setToolTipText("<html><p width=\"500\">" +value+"</p></html>");
    
    0 讨论(0)
  • 2020-12-02 13:13

    Here is a version which I have used before, it works well if you are loading your tool tips from ResourceBundles:

    import javax.swing.JComponent;
    import javax.swing.JToolTip;
    import javax.swing.LookAndFeel;
    import javax.swing.UIManager;
    import javax.swing.plaf.ComponentUI;
    import javax.swing.plaf.ToolTipUI;
    import java.awt.Dimension;
    import java.awt.FontMetrics;
    import java.awt.Graphics;
    import java.util.regex.Pattern;
    
    /**
     * A tooltip that wraps multi-line text.
     */
    public final class MultiLineToolTipUI extends ToolTipUI {
    
        private static final int INSET = 2;
    
        private static final Pattern LINE_SPLITTER = Pattern.compile("$", Pattern.MULTILINE);
    
        private static final MultiLineToolTipUI SHARED_INSTANCE = new MultiLineToolTipUI();
    
        /**
         * Install the multi-line tooltip into the UI manager.
         */
        public static void installUI() {
            String toolTipUI = MultiLineToolTipUI.class.getName();
            UIManager.put("ToolTipUI", toolTipUI);
            UIManager.put(toolTipUI, MultiLineToolTipUI.class);
        }
    
        @SuppressWarnings("UnusedDeclaration")
        public static ComponentUI createUI(JComponent c) {
            return SHARED_INSTANCE;
        }
    
        private MultiLineToolTipUI() {}
    
        @Override
        public Dimension getMaximumSize(JComponent c) {
            return getPreferredSize(c);
        }
    
        @Override
        public Dimension getMinimumSize(JComponent c) {
            return getPreferredSize(c);
        }
    
        @Override
        public Dimension getPreferredSize(JComponent c) {
            String[] lines = LINE_SPLITTER.split(((JToolTip) c).getTipText());
            if (lines.length == 0) {
                return new Dimension(2 * INSET, 2 * INSET);
            }
            FontMetrics metrics = c.getFontMetrics(c.getFont());
            Graphics g = c.getGraphics();
            int w = 0;
            for (String line : lines) {
                w = Math.max(w, (int) metrics.getStringBounds(line, g).getWidth());
            }
            int h = lines.length * metrics.getHeight();
            return new Dimension(w + 2 * INSET, h + 2 * INSET);
        }
    
        @Override
        public void installUI(JComponent c) {
            LookAndFeel.installColorsAndFont(c, "ToolTip.background", "ToolTip.foreground", "ToolTip.font");
            LookAndFeel.installBorder(c, "ToolTip.border");
        }
    
        @Override
        public void paint(Graphics g, JComponent c) {
            int w = c.getWidth(), h = c.getHeight();
            g.setColor(c.getBackground());
            g.fillRect(0, 0, w, h);
            g.setColor(c.getForeground());
            g.drawRect(0, 0, w, h);
            String[] lines = LINE_SPLITTER.split(((JToolTip) c).getTipText());
            if (lines.length != 0) {
                FontMetrics metrics = c.getFontMetrics(c.getFont());
                int height = metrics.getHeight();
                int y = INSET + metrics.getAscent();
                for (String line : lines) {
                    g.drawString(line, INSET, y);
                    y += height;
                }
            }
        }
    
        @Override
        public void uninstallUI(JComponent c) {
            LookAndFeel.uninstallBorder(c);
        }
    
    }
    

    And you would use it by calling this method, before your UI is created:

    MultiLineToolTipUI.installUI();
    

    Then in your properties files just insert newlines to wrap your tool tips as desired.

    0 讨论(0)
  • 2020-12-02 13:16

    Use HTML tooltips and manually break your lines (a simple word tokenizer with a fixed line length should do it). Just make sure your tooltop text starts with "<HTML>". Break lines with "<BR/>" or "<P>". I realize it's not the most clean solution and Java's HTML support is horrible, but it should get things done.

    0 讨论(0)
  • 2020-12-02 13:16

    You can subclass JToolTip, which is a Component, and override createToolTip() on the component.

    0 讨论(0)
  • 2020-12-02 13:21

    I created a utility class that automatically formats strings to a specific length with <br> tags. It is based on the MultiLineToolTips class posted by Paul Taylor, but his has a bug in it that skips portions of the string and does not actually limit the string to a specific length.

    To use my class, simply invoke the splitToolTip method by writing MultiLineToolTips.splitToolTip(yourString); or MultiLineToolTips.splitToolTip(yourString, maxLength); if you want to split it to a specific maximum length. This will create nicely formatted tool tip strings.

    import java.util.ArrayList;
    import java.util.List;
    
    /** A helper class to split strings into a certain length,
     * formatted with html {@literal<br>} tags for multi-line tool tips.
     * Based on the MultiLineToolTips class posted by
     * <a href="https://stackoverflow.com/users/1480018/paul-taylor">Paul Taylor</a>
     * on <a href="https://stackoverflow.com/a/13503677/9567822">Stack Overflow</a>
     * @author <a href="https://stackoverflow.com/users/9567822/andrew-lemaitre?tab=profile">Andrew LeMaitre</a>
     */
    public final class MultiLineToolTips {
    
        /** Private constructor for utility class. */
        private MultiLineToolTips() {
        }
    
        /** Default max length of the tool tip when split with {@link #splitToolTip(String)}. */
        private static final int DIALOG_TOOLTIP_MAX_SIZE = 75;
    
        /** A function that splits a string into sections of {@value #DIALOG_TOOLTIP_MAX_SIZE} characters or less.
         * If you want the lines to be shorter or longer call {@link #splitToolTip(String, int)}.
         * @param toolTip The tool tip string to be split
         * @return the tool tip string with HTML formatting to break it into sections of the correct length
         */
        public static String splitToolTip(final String toolTip) {
            return splitToolTip(toolTip, DIALOG_TOOLTIP_MAX_SIZE);
        }
    
        /**  An overloaded function that splits a tool tip string into sections of a specified length.
         * @param toolTip The tool tip string to be split
         * @param desiredLength The maximum length of the tool tip per line
         * @return The tool tip string with HTML formatting to break it into sections of the correct length
         */
        public static String splitToolTip(final String toolTip, final int desiredLength) {
            if (toolTip.length() <= desiredLength) {
                return toolTip;
            }
    
            List<String>  parts = new ArrayList<>();
            int stringPosition = 0;
    
            while (stringPosition < toolTip.length()) {
                if (stringPosition + desiredLength < toolTip.length()) {
                    String tipSubstring = toolTip.substring(stringPosition, stringPosition + desiredLength);
                    int lastSpace = tipSubstring.lastIndexOf(' ');
                    if (lastSpace == -1 || lastSpace == 0) {
                        parts.add(toolTip.substring(stringPosition, stringPosition + desiredLength));
                        stringPosition += desiredLength;
                    } else {
                        parts.add(toolTip.substring(stringPosition, stringPosition + lastSpace));
                        stringPosition += lastSpace;
                    }
                } else {
                    parts.add(toolTip.substring(stringPosition));
                    break;
                }
            }
    
            StringBuilder  sb = new StringBuilder("<html>");
            for (int i = 0; i < parts.size() - 1; i++) {
                sb.append(parts.get(i) + "<br>");
            }
            sb.append(parts.get(parts.size() - 1));
            sb.append(("</html>"));
            return sb.toString();
        }
    }
    
    0 讨论(0)
  • 2020-12-02 13:23

    This could be improved somewhat, but my approach was a helper function called before setting tooltip that split the tooltip text at provided length, but adjusted to break words on space where possible.

    import java.util.ArrayList;
    import java.util.List;
    
    /**
     *
     */
    public class MultiLineTooltips
    {
        private static int DIALOG_TOOLTIP_MAX_SIZE = 75;
        private static final int SPACE_BUFFER = 10;
    
        public static String splitToolTip(String tip)
        {
            return splitToolTip(tip,DIALOG_TOOLTIP_MAX_SIZE);
        }
        public static String splitToolTip(String tip,int length)
        {
            if(tip.length()<=length + SPACE_BUFFER )
            {
                return tip;
            }
    
            List<String>  parts = new ArrayList<>();
    
            int maxLength = 0;
            String overLong = tip.substring(0, length + SPACE_BUFFER);
            int lastSpace = overLong.lastIndexOf(' ');
            if(lastSpace >= length)
            {
                parts.add(tip.substring(0,lastSpace));
                maxLength = lastSpace;
            }
            else
            {
                parts.add(tip.substring(0,length));
                maxLength = length;
            }
    
            while(maxLength < tip.length())
            {
                if(maxLength + length < tip.length())
                {
                    parts.add(tip.substring(maxLength, maxLength + length));
                    maxLength+=maxLength+length;
                }
                else
                {
                    parts.add(tip.substring(maxLength));
                    break;
                }
            }
    
            StringBuilder  sb = new StringBuilder("<html>");
            for(int i=0;i<parts.size() - 1;i++)
            {
                sb.append(parts.get(i)+"<br>");
            }
            sb.append(parts.get(parts.size() - 1));
            sb.append(("</html>"));
            return sb.toString();
        }
    }
    

    Use like

    jComponent.setToolTipText(MultiLineTooltips.splitToolTip(TOOLTIP));
    
    0 讨论(0)
提交回复
热议问题