Infobulles multilignes en Java?

105

J'essaie d'afficher des info-bulles en Java qui peuvent ou non être de longueur de paragraphe. Comment puis-je encapsuler de longues info-bulles?

Amanda S
la source
Veuillez fournir un exemple de code.
Stefan Thyberg
1
Les info-bulles ne sont-elles pas automatiquement enveloppées de mots si elles sont entourées de balises HTML? Je ne suis pas sûr, donc je ne mets pas cela en réponse.
Paul Tomblin
Paul: Seulement si vous avez des sauts de ligne explicites.
Amanda S

Réponses:

146

Si vous encapsulez l'info-bulle <html>et les </html>balises, vous pouvez couper les lignes avec des <br>balises. Voir http://www.jguru.com/faq/view.jsp?EID=10653 pour des exemples et des discussions.

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/ vue / JMultiLineToolTip.java

Paul Tomblin
la source
1
J'ai utilisé la classe JMultiLineToolTip que vous avez suggérée. Une fois que j'ai utilisé setFixedWidth () pour limiter l'info-bulle à une taille raisonnable, cela a très bien fonctionné. Merci!
Amanda S
24

Le texte de l'info-bulle commençant par " <html>" sera traité comme du HTML. Bien sûr, cela peut être du HTML très large.

Vous pouvez remplacer JComponent.createTooltip pour remplacer l'info-bulle par votre propre composant qui peut afficher tout ce que vous aimez.

Tom Hawtin - Tacle
la source
20

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>");
phwoelfel
la source
Que faire si je souhaite afficher un texte beaucoup plus court que la taille de l'info-bulle? La balise "max-width" ne fonctionne pas ici
nickolay.laptev
5

Utilisez des info-bulles HTML et coupez manuellement vos lignes (un simple tokenizer de mots avec une longueur de ligne fixe devrait le faire). Assurez-vous simplement que le texte de votre tooltop 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.

basszero
la source
4

Exemple:

jTextField1.setToolTipText("<html>"
                              + "Line One"
                              +"<br>"
                              + "Line 2"
                         + "</html>");
ja4
la source
Cela ne répond pas à la question du demandeur. Il posait des questions sur le wrapping lorsqu'il est affiché, pas dans le code source.
Traîneau
2
@ArtB cet exemple de code donne une info-bulle sur deux lignes comme demandé.
Thelema
4

Cela pourrait être quelque peu amélioré, mais mon approche était une fonction d'assistance appelée avant de définir une info-bulle qui divisait le texte de l'info-bulle à la longueur fournie, mais ajustée pour couper les mots dans l'espace lorsque cela était 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));
Paul Taylor
la source
2

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

user101884
la source
1

Voici une version que j'ai utilisée auparavant, cela fonctionne bien si vous chargez vos info-bulles depuis 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 nouvelles lignes pour envelopper vos info-bulles comme vous le souhaitez.

Ian Phillips
la source
1

J'ai créé une classe utilitaire qui formate automatiquement les chaînes à une longueur spécifique avec des <br>balises. 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 à une longueur maximale spécifique. Cela créera des chaînes d'info-bulles 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();
    }
}
Andrew LeMaitre
la source
0

Si vous ajoutez simplement <html>à votre texte d'info-bulle, il semblera fonctionner jusqu'à ce que vous ayez /*...*/ou HTML dans votre texte. Utilisez <html><pre>ou échappez à votre texte. J'ai également dû l'utiliser <font size=3>pour lui donner un aspect assez décent.

NateS
la source