如何创建既具有样式又具有自定义字体的Java / Swing文本组件?

时间:2009-01-19 06:45:09

标签: java swing fonts

如何创建既具有样式又具有自定义字体的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()设置字符串字体,但不能设置自定义字体。

4 个答案:

答案 0 :(得分: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. 在上面的代码段中调用attributes.addAttribute("MyFont", myCustomFont);
  4. 我没有尝试,但我认为它应该有用,或者它可能是一条很好的研究途径。

答案 1 :(得分:2)

jfpoilpret的解决方案完美无缺!为了后人的缘故,这是一个有效的代码片段:

    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!

答案 2 :(得分:0)

您应该尝试使用JEditorPane或JTextPane。

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

答案 3 :(得分:0)

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

(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代码段
p { font-family: "MyFont" }

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

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