Как я могу создать текстовый компонент Java / Swing, который стилизован и имеет собственный шрифт? - PullRequest
1 голос
/ 19 января 2009

Как я могу создать текстовый компонент 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. Обратите внимание, что я мог установить шрифт String с StyleConstants.setFontFamily(), но не с пользовательским шрифтом.

Ответы [ 4 ]

2 голосов
/ 20 января 2009

ОК, теперь я вижу проблему лучше.

После проверки некоторого исходного кода 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); в вашем фрагменте выше

Я не пробовал, но думаю, что это должно сработать, или это может быть хорошим путем для исследования.

2 голосов
/ 20 января 2009

Решение 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!

0 голосов
/ 06 июня 2009

У меня была такая же проблема при написании программы на Clojure, т.е. используя шрифты, загруженные из TTF в JEditorPane, отображающий текст 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 и соответственно создав шрифт с помощью retrieveFont.

Надеюсь, это кому-нибудь поможет:)

0 голосов
/ 19 января 2009

Вместо этого вы должны попробовать использовать JEditorPane или JTextPane.

Они допускают богатый стиль контента по цене более сложного API. К сожалению, если вы ищете пользовательский интерфейс с префектом пикселей, у них также есть дополнительная проблема: они не поддерживают выравнивание базовой линии (функция Java 6).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...