¿Información sobre herramientas de varias líneas en Java?

105

Estoy tratando de mostrar información sobre herramientas en Java que puede o no tener una longitud de párrafo. ¿Cómo puedo ajustar palabras con información sobre herramientas largas?

Amanda S
fuente
Proporcione un ejemplo de código.
Stefan Thyberg
1
¿Las sugerencias sobre herramientas no se ajustan automáticamente a las palabras si están envueltas en etiquetas HTML? No estoy seguro, así que no voy a poner esto como respuesta.
Paul Tomblin
Paul: Solo si tiene saltos de línea explícitos.
Amanda S

Respuestas:

146

Si envuelve la información sobre herramientas <html>y las </html>etiquetas, puede dividir las líneas con <br>etiquetas. Consulte http://www.jguru.com/faq/view.jsp?EID=10653 para ver ejemplos y discusión.

O puede usar la clase JMultiLineToolTip que se puede encontrar en muchos lugares de la red, incluido https://github.com/ls-cwi/yoshiko-app/blob/master/src/main/java/com/yoshiko/internal/ ver / JMultiLineToolTip.java

Paul Tomblin
fuente
1
Usé la clase JMultiLineToolTip que sugirió. Una vez que usé setFixedWidth () para limitar la información sobre herramientas a un tamaño razonable, funcionó muy bien. ¡Gracias!
Amanda S
24

El texto de información sobre herramientas que comienza con " <html>" se tratará como HTML. Por supuesto que podría ser un HTML muy amplio.

Puede anular JComponent.createTooltip para reemplazar la información sobre herramientas con su propio componente que puede mostrar lo que quiera.

Tom Hawtin - tackline
fuente
20

Sé que este es bastante antiguo, ¡pero encontré una solución bastante simple usando código HTML!

Simplemente use un párrafo HTML con un ancho fijo:

setToolTipText("<html><p width=\"500\">" +value+"</p></html>");
phwoelfel
fuente
¿Qué sucede si quiero mostrar texto que es mucho más corto que el tamaño de la información sobre herramientas? La etiqueta "max-width" no funciona aquí
nickolay.laptev
5

Use información sobre herramientas HTML y divida sus líneas manualmente (un simple tokenizador de palabras con una longitud de línea fija debería hacerlo). Solo asegúrese de que el texto de la parte superior de la herramienta comience con "<HTML>". Divida las líneas con "<BR/>" o "<P>". Me doy cuenta de que no es la solución más limpia y el soporte HTML de Java es horrible, pero debería hacer las cosas.

basszero
fuente
4

Ejemplo:

jTextField1.setToolTipText("<html>"
                              + "Line One"
                              +"<br>"
                              + "Line 2"
                         + "</html>");
ja4
fuente
Esto no responde a la pregunta del autor de la pregunta. Estaba preguntando sobre la envoltura cuando se muestra, no en el código fuente.
Trineo
2
@ArtB este código de ejemplo proporciona una información sobre herramientas de dos líneas como se solicita.
Thelema
4

Esto podría mejorarse un poco, pero mi enfoque fue una función auxiliar llamada antes de configurar la información sobre herramientas que dividía el texto de la información sobre herramientas en la longitud proporcionada, pero ajustada para dividir las palabras en el espacio cuando era posible.

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

Usar como

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

Puede crear una subclase de JToolTip, que es un Componente, y anular createToolTip () en el componente.

usuario101884
fuente
1

Aquí hay una versión que he usado antes, funciona bien si está cargando sus consejos sobre herramientas desde 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);
    }

}

Y lo usaría llamando a este método, antes de crear su interfaz de usuario:

MultiLineToolTipUI.installUI();

Luego, en sus archivos de propiedades, simplemente inserte nuevas líneas para ajustar la información sobre herramientas como desee.

Ian Phillips
fuente
1

Creé una clase de utilidad que formatea automáticamente cadenas a una longitud específica con <br>etiquetas. Se basa en la clase MultiLineToolTips publicada por Paul Taylor, pero tiene un error que omite partes de la cadena y en realidad no limita la cadena a una longitud específica.

Para usar mi clase, simplemente invoque el método splitToolTip escribiendo MultiLineToolTips.splitToolTip(yourString);o MultiLineToolTips.splitToolTip(yourString, maxLength);si desea dividirlo en una longitud máxima específica. Esto creará cadenas de información sobre herramientas con un formato agradable.

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
fuente
0

Si solo agrega <html>a su texto de información sobre herramientas, parecerá que funciona hasta que tenga /*...*/o HTML en su texto. Usa <html><pre>o escapa de tu texto. También tuve que usar <font size=3>para que se viera algo decente.

Nates
fuente