Tooltip multilinea in Java?


105

Sto cercando di visualizzare i suggerimenti in Java che possono essere lunghi o meno un paragrafo. Come posso mandare a capo lunghi suggerimenti?


Fornisci un esempio di codice.
Stefan Thyberg

1
I suggerimenti non vanno a capo automaticamente se sono racchiusi in tag HTML? Non ne sono sicuro, quindi non lo sto inserendo come risposta.
Paul Tomblin

Paul: Solo se hai interruzioni di riga esplicite.
Amanda S

Risposte:


146

Se inserisci la descrizione comando <html>e i </html>tag, puoi spezzare le righe con i <br>tag. Vedere http://www.jguru.com/faq/view.jsp?EID=10653 per esempi e discussioni.

Oppure puoi usare la classe JMultiLineToolTip che può essere trovata in molti posti sulla rete, incluso https://github.com/ls-cwi/yoshiko-app/blob/master/src/main/java/com/yoshiko/internal/ vista / JMultiLineToolTip.java


1
Ho usato la classe JMultiLineToolTip che hai suggerito. Dopo aver usato setFixedWidth () per limitare il tooltip a una dimensione ragionevole, ha funzionato benissimo. Grazie!
Amanda S

24

Il testo della descrizione comando che inizia con " <html>" verrà trattato come HTML. Ovviamente potrebbe essere HTML molto ampio.

Puoi sovrascrivere JComponent.createTooltip per sostituire il tooltip con il tuo componente che può visualizzare ciò che ti piace.


20

So che questo è piuttosto vecchio ma ho trovato una soluzione abbastanza semplice usando il codice HTML!

Usa semplicemente un paragrafo HTML con una larghezza fissa:

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

E se volessi visualizzare un testo molto più corto della dimensione del suggerimento? Il tag "max-width" non funziona qui
nickolay.laptev

5

Usa le descrizioni comandi HTML e spezza manualmente le righe (un semplice tokenizzatore di parole con una lunghezza di riga fissa dovrebbe farlo). Assicurati solo che il testo della descrizione comandi inizi con "<HTML>". Interrompi le righe con "<BR/>" o "<P>". Mi rendo conto che non è la soluzione più pulita e il supporto HTML di Java è orribile, ma dovrebbe fare le cose.


4

Esempio:

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

Questo non risponde alla domanda del richiedente. Chiedeva del wrapping quando viene visualizzato, non nel codice sorgente.
Slitta

2
@ArtB questo codice di esempio fornisce un suggerimento di due righe come richiesto.
Thelema

4

Questo potrebbe essere migliorato in qualche modo, ma il mio approccio era una funzione di supporto chiamata prima di impostare il suggerimento che divideva il testo del suggerimento alla lunghezza fornita, ma adattato per spezzare le parole nello spazio dove possibile.

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

Usa mi piace

jComponent.setToolTipText(MultiLineTooltips.splitToolTip(TOOLTIP));

2

È possibile creare una sottoclasse JToolTip, che è un componente, e sovrascrivere createToolTip () sul componente.


1

Ecco una versione che ho usato prima, funziona bene se stai caricando i tuoi suggerimenti sugli strumenti da 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);
    }

}

E lo useresti chiamando questo metodo, prima che la tua interfaccia utente venga creata:

MultiLineToolTipUI.installUI();

Quindi nei file delle proprietà basta inserire le nuove righe per avvolgere i suggerimenti degli strumenti come desiderato.


1

Ho creato una classe di utilità che formatta automaticamente le stringhe a una lunghezza specifica con i <br>tag. Si basa sulla classe MultiLineToolTips pubblicata da Paul Taylor, ma il suo ha un bug che salta parti della stringa e non limita effettivamente la stringa a una lunghezza specifica.

Per usare la mia classe, invoca semplicemente il metodo splitToolTip scrivendo MultiLineToolTips.splitToolTip(yourString);o MultiLineToolTips.splitToolTip(yourString, maxLength);se vuoi dividerlo a una lunghezza massima specifica. Questo creerà stringhe di suggerimenti ben formattate.

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

Se aggiungi solo <html>il testo del suggerimento, sembrerà funzionare finché non avrai /*...*/o HTML nel testo. Usa <html><pre>o esci dal testo. Ho anche dovuto usarlo <font size=3>per farlo sembrare un po 'decente.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.