【问题标题】:JavaFX - subscript and superscript text in TextFlowJavaFX - TextFlow 中的下标和上标文本
【发布时间】:2018-05-11 15:04:30
【问题描述】:

我一直在尝试在 JavaFX 中获取简单的富文本:我希望某些字符为粗体、下标或上标的连续文本。这在普通的 Text 或 Label 类中是不可能的。我试过WebView,但没有成功,因为虽然它会显示这样的文本,但它的大小不适合其内容,因此占据了屏幕的很大一部分,无法控制。

现在我正在尝试使用TextFlow。我可以成功地将Text 对象链接在一起,其中一些可以加粗。然而,下标和上标被证明更加困难。可以简单地通过减小字体大小来模拟下标,但是上标需要将 Text 对象提升到其他对象之上。我找不到这样做的方法:TextFlow 专门忽略了Text 对象的翻译属性,并且我无法覆盖相关Text 上的getBaselineOffset(),因为它是最终的。

我是否必须将Texts 放在 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;
    }
}

【问题讨论】:

    标签: java javafx javafx-8


    【解决方案1】:

    使用-fx-translate-y 可以上下控制文字 您还可以使用 RichTextFX 可用于创建具有不同样式并支持上标和下标的可编辑文本区域

    【讨论】:

    • 如问题中所述,“TextFlow 特别忽略了 Text 对象的翻译属性”。因此,这不起作用。您可以通过将翻译后的 Label 对象放在 TextFlow 中来绕过它,但是您仍然需要根据字体大小来调整翻译,这确实不是一个简洁的解决方案。我在问是否有更好的方法。
    【解决方案2】:

    在文本对象上设置 translateY 属性(在代码中,不确定是否通过 CSS)确实有效 - 自从提出问题以来,它可能发生了一些变化。

    这是一个演示:

        TextFlow container = new TextFlow();
        Text normal = new Text("Normal");
        Text sup = new Text("sup");
        Text sub = new Text("sub");
        sup.setTranslateY(normal.getFont().getSize() * -0.3);
        sub.setTranslateY(normal.getFont().getSize() * 0.3);
        container.getChildren().addAll(normal, sup, sub);
    

    它是这样的:

    我在 Mac 上使用 JavaFX 11,以防最终影响这是否真的有效。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-08-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多