【问题标题】:How can I create a Java/Swing text component that is both styled and has a custom font?如何创建既具有样式又具有自定义字体的 Java/Swing 文本组件?
【发布时间】:2010-10-02 04:29:52
【问题描述】:

如何创建既具有样式又具有自定义字体的 Java/Swing 文本组件?我想用红色突出显示一小部分文本,但同时使用自定义(通过Font.createFont 嵌入)字体。 JLabel 接受 HTML 文本,它允许我突出显示部分文本,但在呈现 HTML 时它会忽略字体设置。其他文本组件(例如 JTextArea)将使用自定义字体,但它们不会呈现 HTML。最简单的方法是什么?

以下是使用 JTextPane 失败的示例:

    JTextPane textPane = new JTextPane();
    textPane.setFont(myCustomFont);
    textPane.setText(text);
    MutableAttributeSet attributes = new SimpleAttributeSet();
    StyleConstants.setForeground(attributes, Color.RED);
    textPane.getStyledDocument().setCharacterAttributes(
        text.indexOf(toHighlight),
        toHighlight.length(),
        attributes, true
    );

这成功地显示了文本,其中“toHighlight”部分以红色突出显示,但它不使用 myCustomFont。请注意,我可以使用StyleConstants.setFontFamily() 设置字符串字体,但不能使用自定义字体。

【问题讨论】:

    标签: java swing fonts


    【解决方案1】:

    您应该尝试改用 JEditorPane 或 JTextPane。

    它们以更复杂的 API 为代价,让内容具有丰富的风格。 不幸的是,如果您正在寻找像素完美的 UI,它们还有一个额外的问题:它们不支持基线对齐(Java 6 功能)。

    【讨论】:

    • 我已经尝试了这两种方法,但仍然遇到同样的问题。如果我使用 StyledDocument,它会忽略我拥有的任何字体设置,并坚持我使用“FontFamily”设置字体,它只允许使用字符串——而不是自定义字体。
    • 您能否展示一个 sn-p 来显示您对 StyledDocument 所做的事情,但它不起作用?
    • 我在问题中添加了一个更详细的示例。希望这将有助于澄清我正在尝试做的事情。
    【解决方案2】:

    好的,我现在更清楚地看到了问题。

    在检查了一些 Swing 源代码后,很明显您不能使用 DefaultStyledDocument 并让它使用开箱即用的物理字体(您自己使用 createFont 创建的字体)。

    但是,我认为您可以通过这种方式实现自己的StyleContext

    public class MyStyleContext extends javax.swing.text.StyleContext
    {
        @Override public Font getFont(AttributeSet attr)
        {
            Font font = attr.getAttribute("MyFont");
            if (font != null)
                return font;
            else
                return super.getFont(attr);
        }
    }
    

    那么你必须:

    1. 创建一个DefaultStyledDocument 一个new MyStyleContext()
    2. “附加”到JTextPane
    3. 在上面的 sn-p 中调用 attributes.addAttribute("MyFont", myCustomFont);

    我没有尝试过,但我认为它应该可以工作,或者这可能是一个很好的调查途径。

    【讨论】:

    • 完美运行。下面的代码示例。再次感谢。 :)
    【解决方案3】:

    jfpoilpret 的解决方案效果很好!为了后代的缘故,这是一个工作代码sn-p:

        JTextPane textPane = new JTextPane();
        textPane.setStyledDocument(new DefaultStyledDocument(new StyleContext() {
            @Override
            public Font getFont(AttributeSet attr) {
                return myCustomFont;
            }
        }));
        textPane.setText(text);
        MutableAttributeSet attributes = new SimpleAttributeSet();
        StyleConstants.setForeground(attributes, Color.RED);
        textPane.getStyledDocument().setCharacterAttributes(
            text.indexOf(toHighlight),
            toHighlight.length(),
            attributes, true
        );
    

    谢谢,jfpoilpret!

    【讨论】:

      【解决方案4】:

      我在 Clojure 中编写程序时遇到了同样的问题,即。在显示 HTML 文本的 JEditorPane 中使用从 TTF 加载的字体。这里的解决方案工作正常 - 我在这里复制有趣的部分以供将来参考:

      (def font1 (with-open [s (FileInputStream. "SomeFont.ttf")]
                   (.deriveFont (Font/createFont Font/TRUETYPE_FONT s) (float 14))))
      (def font2 (Font. "SansSerif") Font/PLAIN 14)
      (let [editor (JEditorPane. "text/html" "")]
        (.setDocument editor
                      (proxy [HTMLDocument] []
                        (getFont [attr]
                          (if (= (.getAttribute attr StyleConstants/FontFamily)
                                 "MyFont")
                            font1
                            font2)))))
      

      这假定 HTML 文档引用了字体系列“MyFont”,例如使用 CSS sn-p 之类的

      p { font-family: "MyFont" }
      

      请注意,您必须处理 所有 字体请求。这是因为 proxy 的限制不能调用超类的成员函数。此外,如果您想处理不同的字体大小,则必须“手动”执行此操作,检查 StyleConstants/FontSize 属性并相应地创建一个带有 derivedFont 的字体。

      我希望这会对某人有所帮助:)

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2020-04-28
        • 2022-01-07
        • 1970-01-01
        • 2021-02-08
        • 1970-01-01
        • 1970-01-01
        • 2020-06-17
        相关资源
        最近更新 更多