How to create a Java / Swing text component that has both styles and has its own font?

How to create a Java / Swing text component that has both styles and has its own font? I want to highlight a small part of the text in red, but at the same time use a special (built-in through Font.createFont ) font. JLabel accepts HTML text, which allows me to highlight some of the text, but it ignores the font settings when rendering HTML. Other text components, such as JTextArea, will use a custom font, but they will not display HTML. What is the easiest way to do both?

Here is an example of a failed use of 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 ); 

This successfully displays text with the "toHighlight" portion highlighted in red, but does not use myCustomFont. Note that I can set the String font with StyleConstants.setFontFamily() , but not a custom font.

+1
source share
4 answers

Ok, now I see the problem better.

After checking the Swing source code, it is clear that you cannot use the DefaultStyledDocument and use the physical font (the one you created using createFont ) out of the box.

However, what I think you could do is implement your own StyleContext as follows:

 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); } } 

Then you need to:

  • create DefaultStyledDocument using a new MyStyleContext()
  • "attach" it to JTextPane
  • calling attributes.addAttribute("MyFont", myCustomFont); in your snippet above

I haven't tried it, but I think this should work, or it could be a good way to research.

+2
source
Decision

jfpoilpret worked great! For posterity, here is a snippet of working code:

  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 ); 

Thank jfpoilpret

+2
source

Instead, try using JEditorPane or JTextPane.

They allow you to use a rich content style for the price of a more complex API. Unfortunately, if you are looking for a user interface with a prefect pixel, they also have an additional problem: they do not support baseline alignment (Java 6 feature).

0
source

I had the same problem when writing a program in Clojure, i.e. using fonts downloaded from TTF to JEditorPane displaying HTML text. The solution worked well here - I copy the interesting part here for future reference:

 (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))))) 

This assumes that the HTML document belongs to the "MyFont" font family, for example. with CSS snippet like

 p { font-family: "MyFont" } 

Please note that with this you must handle all font requests. This is because the proxy restriction cannot call member functions of the superclass. In addition, if you want to handle different font sizes, you must do this "manually" by checking the StyleConstants / FontSize attribute and creating the font using deiveFont, respectively.

Hope this helps someone :)

0
source

Source: https://habr.com/ru/post/1385227/


All Articles