web-dev-qa-db-fra.com

Infobulles multilignes en Java?

J'essaie d'afficher des info-bulles dans Java qui peut ou non être de la longueur d'un paragraphe. Comment puis-je envelopper des info-bulles longues?

101
Amanda S

Si vous enveloppez l'info-bulle dans <html> et </html> tags, vous pouvez couper les lignes avec <br> Mots clés. Voir http://www.jguru.com/faq/view.jsp?EID=1065 pour des exemples et une discussion.

Ou vous pouvez utiliser la classe JMultiLineToolTip qui peut être trouvée à de nombreux endroits sur le net, y compris https://github.com/ls-cwi/yoshiko-app/blob/master/src/main/Java/com/ yoshiko/internal/view/JMultiLineToolTip.Java

143
Paul Tomblin

Texte de l'infobulle commençant par "<html> "sera traité comme du HTML. Bien sûr, il pourrait s'agir d'un code HTML très large.

Vous pouvez remplacer JComponent.createTooltip pour remplacer l'infobulle par votre propre composant qui peut afficher ce que vous voulez.

24

Je sais que celui-ci est assez ancien mais j'ai trouvé une solution assez simple en utilisant du code HTML!

Utilisez simplement un paragraphe HTML avec une largeur fixe:

setToolTipText("<html><p width=\"500\">" +value+"</p></html>");
19
phwoelfel

Utilisez des info-bulles HTML et coupez manuellement vos lignes (un simple tokenizer Word avec une longueur de ligne fixe devrait le faire). Assurez-vous simplement que le texte de votre outil commence par "<HTML>". Coupez les lignes avec "<BR/>" ou "<P>". Je me rends compte que ce n'est pas la solution la plus propre et que le support HTML de Java est horrible, mais cela devrait faire avancer les choses.

5
basszero

Exemple:

jTextField1.setToolTipText("<html>"
                              + "Line One"
                              +"<br>"
                              + "Line 2"
                         + "</html>");
4
ja4

Vous pouvez sous-classer JToolTip, qui est un composant, et remplacer createToolTip () sur le composant.

2
user101884

Cela pourrait être quelque peu amélioré, mais mon approche était une fonction d'aide appelée avant de définir l'info-bulle qui divise le texte de l'info-bulle à la longueur fournie, mais ajustée pour casser les mots dans l'espace lorsque cela est 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();
    }
}

Utilisez comme

jComponent.setToolTipText(MultiLineTooltips.splitToolTip(TOOLTIP));
2
Paul Taylor

Voici une version que j'ai utilisée auparavant, elle fonctionne bien si vous chargez vos info-bulles à partir de 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);
    }

}

Et vous l'utiliseriez en appelant cette méthode, avant la création de votre interface utilisateur:

MultiLineToolTipUI.installUI();

Ensuite, dans vos fichiers de propriétés, insérez simplement des retours à la ligne pour envelopper vos info-bulles comme vous le souhaitez.

1
Ian Phillips

J'ai créé une classe utilitaire qui formate automatiquement les chaînes à une longueur spécifique avec des balises <br>. Il est basé sur la classe MultiLineToolTips publiée par Paul Taylor, mais il contient un bogue qui saute des parties de la chaîne et ne limite pas réellement la chaîne à une longueur spécifique.

Pour utiliser ma classe, appelez simplement la méthode splitToolTip en écrivant MultiLineToolTips.splitToolTip(yourString); ou MultiLineToolTips.splitToolTip(yourString, maxLength); si vous souhaitez la diviser en une longueur maximale spécifique. Cela créera des chaînes d'infobulles bien formatées.

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();
    }
}
1
Andrew LeMaitre

Si vous ajoutez simplement <html> à votre info-bulle, il semblera fonctionner jusqu'à ce que vous ayez /*...*/ ou HTML dans votre texte. Utilisation <html><pre> ou échappez à votre texte. J'ai aussi dû utiliser <font size=3> pour le rendre quelque peu décent.

0
NateS