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

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

Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
1
0
3 368
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

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

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

Я пробовал оба из них, но все еще с той же проблемой. Если я использую StyledDocument, он игнорирует любые настройки шрифта, которые у меня есть, и настаивает на том, чтобы я устанавливал шрифты с помощью «FontFamily», который допускает только строку, а не пользовательский шрифт.

Ross 19.01.2009 10:22

Не могли бы вы показать фрагмент, который показывает, что вы сделали с StyledDocument, и это не работает?

jfpoilpret 19.01.2009 10:30

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

Ross 19.01.2009 20:15
Ответ принят как подходящий

Хорошо, теперь я лучше понимаю проблему.

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

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

Сработало отлично. Пример кода ниже. Еще раз спасибо. :)

Ross 20.01.2009 04:47

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

У меня была такая же проблема при написании программы на 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" }

Обратите внимание, что при этом вы должны обрабатывать запросы шрифта все. Это связано с тем, что доверенное лицо не может вызывать функции-члены суперкласса. Кроме того, если вы хотите обрабатывать шрифты разных размеров, вы должны сделать это «вручную», проверив атрибут StyleConstants / FontSize и соответственно создав шрифт с помощью deriveFont.

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

Другие вопросы по теме