Wieloliniowe podpowiedzi w Javie?


105

Próbuję wyświetlić podpowiedzi w Javie, które mogą, ale nie muszą, mieć długość akapitu. Jak mogę zawijać długie etykiety narzędzi?


Podaj przykładowy kod.
Stefan Thyberg

1
Czy podpowiedzi narzędziowe nie są automatycznie zawijane, jeśli są opakowane w znaczniki HTML? Nie jestem pewien, więc nie umieszczam tego jako odpowiedzi.
Paul Tomblin

Paul: Tylko jeśli masz wyraźne podziały wierszy.
Amanda S

Odpowiedzi:


146

Jeśli zawiniesz etykietkę narzędzi <html>i </html>etykiety, możesz przerywać linie za pomocą <br>etykiet. Przykłady i dyskusje można znaleźć pod adresem http://www.jguru.com/faq/view.jsp?EID=10653 .

Lub możesz użyć klasy JMultiLineToolTip, którą można znaleźć w wielu miejscach w sieci, w tym https://github.com/ls-cwi/yoshiko-app/blob/master/src/main/java/com/yoshiko/internal/ view / JMultiLineToolTip.java


1
Skorzystałem z zaproponowanej przez Ciebie klasy JMultiLineToolTip. Kiedy użyłem setFixedWidth (), aby ograniczyć podpowiedź do rozsądnego rozmiaru, działało świetnie. Dzięki!
Amanda S

24

Tekst podpowiedzi zaczynający się od „ <html>” będzie traktowany jak HTML. Oczywiście może to być bardzo szeroki HTML.

Możesz zastąpić JComponent.createTooltip, aby zastąpić etykietkę własnym komponentem, który może wyświetlać dowolne obrazy.


20

Wiem, że ten jest dość stary, ale znalazłem dość proste rozwiązanie za pomocą kodu HTML!

Po prostu użyj akapitu HTML o stałej szerokości:

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

Co zrobić, jeśli chcę wyświetlić tekst, który jest znacznie krótszy niż rozmiar etykiety narzędzi? Tag „max-width” nie działa tutaj
nickolay.laptev

5

Skorzystaj z podpowiedzi HTML i ręcznie przerywaj wiersze (wystarczy prosty tokenizer słów o ustalonej długości). Upewnij się tylko, że tekst na górze narzędzia zaczyna się od „<HTML>”. Łam linie za pomocą „<BR/>” lub „<P>”. Zdaję sobie sprawę, że nie jest to najczystsze rozwiązanie, a obsługa HTML w Javie jest okropna, ale powinno załatwić sprawę.


4

Przykład:

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

To nie odpowiada na pytanie pytającego. Pytał o opakowanie, kiedy jest wyświetlane, a nie w kodzie źródłowym.
Sanki

2
@ArtB ten przykładowy kod daje dwuwierszową podpowiedź zgodnie z zapytaniem.
Thelema

4

Można to nieco poprawić, ale moim podejściem była funkcja pomocnicza wywoływana przed ustawieniem podpowiedzi, która dzieli tekst podpowiedzi na określoną długość, ale dostosowaną do łamania słów w przestrzeni, gdzie to możliwe.

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

Użyj like

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

2

Można utworzyć podklasę JToolTip, która jest komponentem, i nadpisać metodę createToolTip () w komponencie.


1

Oto wersja, z której korzystałem wcześniej, działa dobrze, jeśli ładujesz wskazówki dotyczące narzędzi z 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);
    }

}

I można go użyć, wywołując tę ​​metodę, zanim zostanie utworzony interfejs użytkownika:

MultiLineToolTipUI.installUI();

Następnie w plikach właściwości po prostu wstaw nowe linie, aby zawinąć wskazówki narzędzi zgodnie z potrzebami.


1

Stworzyłem klasę narzędziową, która automatycznie formatuje ciągi do określonej długości za pomocą <br> tagów. Opiera się na klasie MultiLineToolTips opublikowanej przez Paula Taylora, ale ma w nim błąd, który pomija fragmenty ciągu i w rzeczywistości nie ogranicza ciągu do określonej długości.

Aby użyć mojej klasy, po prostu wywołaj metodę splitToolTip, pisząc MultiLineToolTips.splitToolTip(yourString);lub MultiLineToolTips.splitToolTip(yourString, maxLength);jeśli chcesz podzielić ją na określoną maksymalną długość. Stworzy to ładnie sformatowane ciągi podpowiedzi.

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

Jeśli po prostu dodasz <html>do tekstu podpowiedzi, będzie on działał, dopóki nie będziesz mieć /*...*/HTML w tekście. Użyj <html><pre>tekstu lub ucieknij przed nim. Musiałem też użyć, <font size=3>aby wyglądało to trochę przyzwoicie.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.