4

Is it possible to change the background color of a paragraph in Java Swing? I tried to set it using the setParagraphAttributes method (code below) but doesn't seem to work.

    StyledDocument doc = textPanel.getStyledDocument();
    Style style = textPanel.addStyle("Hightlight background", null);
    StyleConstants.setBackground(style, Color.red);

    Style logicalStyle = textPanel.getLogicalStyle();
    doc.setParagraphAttributes(textPanel.getSelectionStart(), 1, textPanel.getStyle("Hightlight background"), true);
    textPanel.setLogicalStyle(logicalStyle);
Sudar
  • 18,954
  • 30
  • 85
  • 131
  • Note that setting paragraph element attributes (correctly) with a certain background colour will affect only the characters of that paragraph. It won't affect the space to the right (or left) of the paragraph. However, a custom `Highlighter.HighlightPainter` could be supplied to the `JTextComponent`'s `Highlighter` to be able to do that. – Evgeni Sergeev May 11 '16 at 08:54

4 Answers4

3

UPDATE: I just found out about a class called Highlighter.I dont think you should be using the setbackground style. Use the DefaultHighlighter class instead.

Highlighter h = textPanel.getHighlighter();
h.addHighlight(1, 10, new DefaultHighlighter.DefaultHighlightPainter(
            Color.red));

The first two parameters of the addHighlight method are nothing but the starting index and ending index of the text you want to highlight. You can call this method multiple timesto highlight discontinuous lines of text.

OLD ANSWER:

I have no idea why the setParagraphAttributes method doesnt seem to work. But doing this seems to work.

    doc.insertString(0, "Hello World", textPanel.getStyle("Hightlight background"));

Maybe you can work a hack around this for now...

Jaskirat
  • 1,114
  • 1
  • 8
  • 17
  • Thanks for the reply. The above code works, but it changes the background color only, if the text is present. I want the background color to be changed, even if the text is not present. (Like the background color property in CSS) – Sudar Oct 30 '09 at 08:27
  • You specify the tag you are altering the background color of in css. What would you do in a jtextpane? The question is , you have to figure of what demarcates a paragraph for you and set the color no? You can either specify the characters(or predesignated pixel areas if you want) or the whole pane. Or use JEditorPane, I think CSS works in JEditorPane... – Jaskirat Oct 30 '09 at 08:50
  • BTW just tried css and even in css you cant have bgcolor without any text in the para. Dunno what exactly you mean... I tried this `

    This is a paragraph.

    The below para doesnt contain any text so its not highlighted...

    – Jaskirat Oct 30 '09 at 08:55
3

I use:

SimpleAttributeSet background = new SimpleAttributeSet();
StyleConstants.setBackground(background, Color.RED);

Then you can change existing attributes using:

doc.setParagraphAttributes(0, doc.getLength(), background, false);

Or add attributes with text:

doc.insertString(doc.getLength(), "\nEnd of text", background );
camickr
  • 321,443
  • 19
  • 166
  • 288
  • I don't want the entire text pane to be colored. I want only one paragraph to be colored. I tried your approach and it doesn't seem to work. – Sudar Oct 30 '09 at 07:04
  • The given two examples of setting a background are not the same. The `doc.setParagraphAttributes()` with a background color has no effect with `DefaultStyledDocument` – the background color is only painted at the character run level. That's what `doc.insertString()` with attributes does: `doc.setCharacterAttributes()`. – Stanimir Stamenkov Mar 25 '23 at 14:16
0

Easy way to change the background color of selected text or paragraph.

  //choose color from JColorchooser
  Color color = colorChooser.getColor();

  //starting position of selected Text
  int start = textPane.getSelectedStart();

  // end position of the selected Text
  int end = textPane.getSelectionEnd();

  // style document of text pane where we change the background of the text
  StyledDocument style = textPane.getStyledDocument();

  // this old attribute set of selected Text;
  AttributeSet oldSet = style.getCharacterElement(end-1).getAttributes();

  // style context for creating new attribute set.
  StyleContext sc = StyleContext.getDefaultStyleContext();

  // new attribute set with new background color
  AttributeSet s = sc.addAttribute(oldSet, StyleConstants.Background, color);

 // set the Attribute set in the selected text
  style.setCharacterAttributes(start, end- start, s, true);
Ganesh Patel
  • 450
  • 5
  • 15
0

If you want the background of the whole paragraph box to be painted you need a custom ViewFactory (therefore a custom EditorKit providing it) that produces Box/Paragraph views knowing to paint their own background.

With HTMLDocument/HTMLEditorKit this is implemented by StyleSheet.getBoxPainter(), for example.

Here's my solution for DefaultStyledDocument/StyledEditorKit:

//package ;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.awt.Shape;

import javax.swing.text.AbstractDocument;
import javax.swing.text.AttributeSet;
import javax.swing.text.Element;
import javax.swing.text.Style;
import javax.swing.text.StyleConstants;
import javax.swing.text.StyledEditorKit;
import javax.swing.text.View;
import javax.swing.text.ViewFactory;

public class BoxBackgroundFactory implements ViewFactory {

    private final ViewFactory viewFactory;

    public BoxBackgroundFactory(ViewFactory viewFactory) {
        this.viewFactory = viewFactory;
    }

    @Override
    public View create(Element elem) {
        String kind = elem.getName();
        if (AbstractDocument.ParagraphElementName.equals(kind)) {
            return new ParagraphView(elem);
        } else if (AbstractDocument.SectionElementName.equals(kind)) {
            return new BoxView(elem);
        }
        return viewFactory.create(elem);
    }

    @SuppressWarnings("serial")
    public static StyledEditorKit newEditorKit() {
        return new StyledEditorKit() {
            private final BoxBackgroundFactory boxbgFactory =
                    new BoxBackgroundFactory(super.getViewFactory());
            @Override public ViewFactory getViewFactory() {
                return boxbgFactory;
            }
        };
    }

    static void paintBackground(View view, Graphics g, Shape a) {
        Color bg = null;
        AttributeSet atts = view.getAttributes();
        if (atts.isDefined(StyleConstants.Background)) {
            bg = (Color) atts.getAttribute(StyleConstants.Background);
        } else {
            AttributeSet linked = atts.getResolveParent();
            if (linked instanceof Style)
                bg = (Color) linked.getAttribute(StyleConstants.Background);
        }
        if (bg == null) return;

        Rectangle rect = (a instanceof Rectangle) ? (Rectangle) a : a.getBounds();
        g.setColor(bg);
        g.fillRect(rect.x, rect.y, rect.width, rect.height);
    }


    private static class BoxView extends javax.swing.text.BoxView {

        BoxView(Element elem) {
            super(elem, View.Y_AXIS);
        }

        @Override
        public void paint(Graphics g, Shape a) {
            paintBackground(this, g, a);
            super.paint(g, a);
        }

    } // class BoxView


    private static class ParagraphView extends javax.swing.text.ParagraphView {

        ParagraphView(Element elem) {
            super(elem);
        }

        @Override
        public void paint(Graphics g, Shape a) {
            paintBackground(this, g, a);
            super.paint(g, a);
        }

    } // class ParagraphView


} // class BoxBackgroundFactory

Here's a demo using it (with comparison to few of the other suggestions):

//package ;

import java.awt.Color;

import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextPane;
import javax.swing.SwingUtilities;
import javax.swing.text.BadLocationException;
import javax.swing.text.DefaultHighlighter;
import javax.swing.text.Style;
import javax.swing.text.StyleConstants;
import javax.swing.text.StyleContext;
import javax.swing.text.StyledDocument;

@SuppressWarnings("serial")
public class BoxBackgroundDemo extends JFrame {

    BoxBackgroundDemo() {
        super("Box background demo");
        super.setDefaultCloseOperation(DISPOSE_ON_CLOSE);

        JTextPane editor = new JTextPane();
        editor.setEditorKit(BoxBackgroundFactory.newEditorKit());

        StyledDocument document = editor.getStyledDocument();
        Style defaultStyle = document.getStyle(StyleContext.DEFAULT_STYLE);
        StyleConstants.setSpaceAbove(defaultStyle, 5f);
        StyleConstants.setSpaceBelow(defaultStyle, 5f);
        Style highlight = document.addStyle("hilite", defaultStyle);
        StyleConstants.setBackground(highlight, Color.RED);
        StyleConstants.setForeground(highlight, Color.YELLOW);

        String paragraph = "The quick brown fox jumps over the lazy fox. 1234567890\n";
        try {
            document.insertString(0, paragraph, null);
            document.insertString(document.getLength(), paragraph, null);
            document.setCharacterAttributes(paragraph.length() / 2,
                    paragraph.length(), highlight, false);

            // Two paragraphs background
            document.insertString(document.getLength(), paragraph, null);
            document.insertString(document.getLength(), paragraph, null);
            document.setParagraphAttributes(paragraph.length() * 5 / 2,
                    paragraph.length(), highlight, false);

            document.insertString(document.getLength(), paragraph, null);
            document.insertString(document.getLength(), paragraph, null);
            editor.getHighlighter().addHighlight(
                    paragraph.length() * 9 / 2, paragraph.length() * 11 / 2,
                    new DefaultHighlighter.DefaultHighlightPainter(Color.RED));

            // Single paragraph background
            document.insertString(document.getLength(), paragraph, null);
            document.setLogicalStyle(paragraph.length() * 6, highlight);

        } catch (BadLocationException e) {
            e.printStackTrace();
        }

        super.add(new JScrollPane(editor));
    }

    public static void main(String[] args) throws Exception {
        SwingUtilities.invokeLater(() -> {
            BoxBackgroundDemo window = new BoxBackgroundDemo();
            window.pack();
            window.setLocationRelativeTo(null);
            window.setVisible(true);
        });
    }

}

demo

In my opinion, a custom highlight painter implementation would be the least suitable approach for this purpose.