在JTextPane(Java Swing)中更改段落的背景颜色

4

在Java Swing中,是否可以更改段落的背景颜色?我尝试使用setParagraphAttributes方法进行设置(如下所示),但似乎不起作用。

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

请注意,使用特定背景颜色正确设置段落元素属性只会影响该段落的字符,而不会影响段落右侧(或左侧)的空格。但是,可以提供自定义的Highlighter.HighlightPainter来供JTextComponentHighlighter使用,以实现此功能。 - Evgeni Sergeev
4个回答

3

我使用:

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

然后您可以使用以下方式更改现有属性:

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

或者添加带有文本的属性:

doc.insertString(doc.getLength(), "\nEnd of text", background );

我不想让整个文本窗格都变色,我只想让一个段落变色。我尝试了你的方法,但似乎不起作用。 - Sudar
当然可以。您需要做的就是更改起始值和长度值。也就是阅读API以了解每个方法的参数如何工作。 - camickr
给出的两个设置背景的示例并不相同。使用背景颜色的doc.setParagraphAttributes()DefaultStyledDocument中没有效果 - 背景颜色仅在字符运行级别上绘制。这就是doc.insertString()与属性所做的:doc.setCharacterAttributes() - Stanimir Stamenkov

3

更新: 我刚刚了解到一个名为Highlighter的类,建议您不要使用setbackground样式,而是使用DefaultHighlighter类。

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

addHighlight方法的前两个参数是要高亮文本的起始索引和结束索引。您可以多次调用此方法来突出显示不连续的文本行。

旧答案:

我不知道为什么setParagraphAttributes方法似乎不起作用。但是这样做似乎有效。

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

也许你现在可以通过一些技巧来解决这个问题...

谢谢回复。上面的代码可以工作,但是只有在文本存在时才会更改背景颜色。我希望即使没有文本也能更改背景颜色。(就像CSS中的背景颜色属性) - Sudar
在CSS中,您可以指定要更改背景颜色的标签。那么在JTextPane中该怎么做呢?问题是,您必须找出为您划分段落的内容,并设置颜色,对吧?您可以指定字符(或预先设计的像素区域,如果您想这样做),也可以指定整个窗格。或者使用JEditorPane,我认为CSS在JEditorPane中也可以使用... - Jaskirat
顺便说一下,我刚尝试了CSS,即使使用CSS,你也不能将bgcolor应用到没有文本的段落中。不知道你具体指什么... 我尝试了这个:<html><head> <style type="text/css"> p {background-color:rgb(255,0,255);} </style> </head> <p>这是一个段落。</p> 下面的段落没有任何文本,因此它没有突出显示... <p></p> </body></html> - Jaskirat

0

更改所选文本或段落的背景颜色的简单方法。

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

0

如果您想要整个段落框的背景被涂上,您需要一个自定义的ViewFactory(因此提供它的自定义EditorKit),它生成知道如何绘制自己背景的Box/Paragraph视图。

使用HTMLDocument/HTMLEditorKit,例如通过StyleSheet.getBoxPainter()实现。

这是我针对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

这是一个使用它的演示(与其他几个建议进行比较):
//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

在我看来,为此目的编写自定义 highlight 绘制实现是最不合适的方法。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接