JavaFX - подстрочный и надстрочный текст в TextFlow - PullRequest
0 голосов
/ 11 мая 2018

Я пытался получить простой форматированный текст в JavaFX: мне нужен непрерывный текст, где некоторые символы выделены жирным шрифтом, нижним или верхним индексом. Это невозможно в обычных классах Text или Label. Я попытался WebView безуспешно, так как, хотя он будет отображать такой текст, он не изменяет размер своего содержимого и, таким образом, занимает неконтролируемо большую часть экрана.

Теперь я пытаюсь использовать TextFlow. Я могу успешно связать вместе Text объекты, некоторые из которых можно выделить жирным шрифтом. Однако нижний и верхний индексы оказываются более сложными. Подстрочный индекс можно эмулировать, просто уменьшая размер шрифта, однако верхний индекс требует, чтобы объект Text был поднят над остальными. Я не могу найти способ сделать это: TextFlow специально игнорирует свойства перевода объектов Text, и я не могу переопределить getBaselineOffset() для рассматриваемого Text, так как он является окончательным.

Должен ли я поместить Text в HBox? Неужели в JavaFX такой поддержки нет? То, что я пытаюсь сделать, не сложно; кажется ошеломляющим, что нет встроенной поддержки нижнего и верхнего индексов.

import javafx.scene.text.Text;
import javafx.scene.text.TextAlignment;
import javafx.scene.text.TextFlow;

import java.util.LinkedList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public final class TextFlowBuilder
{
private static final String BOLD = "<b>";
private static final String UN_BOLD = "</b>";

private static final String SUPERSCRIPT = "<sup>";
private static final String UN_SUPERSCRIPT = "</sup>";

private static final String SUBSCRIPT = "<sub>";
private static final String UN_SUBSCRIPT = "</sub>";

private static final Pattern NOT_JUST_WHITESPACE = Pattern.compile("\\S");
private static final Pattern CHARACTER_CODE = Pattern.compile("&#(\\d+);");

public static TextFlow htmlToTextFlow(final String html, final int fontSize, final TextAlignment alignment)
{
    final String[] split = html.split("(?<=>)|(?=<)");  //Split before and after tags, splitting it into a series of tags and tag contents.
    final List<Text> texts = new LinkedList<>();

    boolean b = false;
    boolean sup = false;
    boolean sub = false;

    for (String segment : split)
    {
        switch (segment)
        {
            case BOLD:
                b = true;
                break;
            case UN_BOLD:
                b = false;
                break;
            case SUPERSCRIPT:
                sup = true;
                break;
            case UN_SUPERSCRIPT:
                sup = false;
                break;
            case SUBSCRIPT:
                sub = true;
                break;
            case UN_SUBSCRIPT:
                sub = false;
                break;

            default:
                //Add as text if string is not a tag, and is more than just whitespace.
                if (segment.length() > 0
                        && NOT_JUST_WHITESPACE.matcher(segment).find()
                        && !segment.startsWith("<"))
                {
                    final Matcher m = CHARACTER_CODE.matcher(segment);
                    while (m.find())
                    {
                        final String specialChar = Character.toString((char)Integer.parseInt(m.group(1)));
                        segment = m.replaceFirst(specialChar);
                    }

                    final Text t = new Text(segment);
                    String style = "";
                    if (b)
                        style += "-fx-font-weight: bold; ";
                    if (sup)
                    {
                        style += String.format("-fx-font-size: %f.3; ", fontSize/1.75);
                        //Need to move text to above the rest
                    }
                    else if (sub)
                    {
                        style += String.format("-fx-font-size: %f.3; ", fontSize/1.75);
                    }
                    else
                    {
                        style += String.format("-fx-font-size: %d; ", fontSize);
                    }
                    t.setStyle(style);
                    texts.add(t);
                }
        }
    }

    final Text[] textsAsArray = new Text[texts.size()];
    final TextFlow tf = new TextFlow(texts.toArray(textsAsArray));
    tf.setTextAlignment(alignment);
    return tf;
    }
}

1 Ответ

0 голосов
/ 21 мая 2018

Использование -fx-translate-y Вы можете управлять текстом вверх и вниз. Вы также можете использовать RichTextFX, который можно использовать для создания редактируемой текстовой области с различными стилями и поддержкой Superscript и Subscript

...