如何在JTextPane中设置自定义行背景颜色

9
我希望能够在我的JTextPane中每一行交替使用灰色和白色作为背景。我尝试通过重载paintComponent()方法并根据组件高度和字体大小手动绘制背景来实现,但是我没有成功。
请问有什么提示吗?

“一行”是什么意思?如果你交替使用颜色,setBackgroud()方法会失效吗? - jzd
你的文本窗格可编辑吗?也就是说,如果添加或删除行,你是否希望背景发生变化? - dogbane
5个回答

2
您可以使用由@VonC编写的行高亮器(此处此处)来回答这个问题
为了突出显示交替行,您可以按以下方式使用它:
public static void main(String[] args)  {

    JTextPane t = new JTextPane();
    t.setSelectionColor(new Color(1.0f, 1.0f, 1.0f, 0.0f));
    Highlighter hilite = new MyHighlighter();
    t.setHighlighter(hilite);
    t.setText("Line1\nLine2\nLine3\nLine4\nLine5\n");


    DefaultHighlightPainter whitePainter = new DefaultHighlighter.DefaultHighlightPainter(Color.WHITE);
    DefaultHighlightPainter grayPainter = new DefaultHighlighter.DefaultHighlightPainter(Color.GRAY);

    try {
        Document doc = t.getDocument();
        String text = doc.getText(0, doc.getLength());
        int start = 0;
        int end = 0 ;

        boolean even = true;

        //look for newline char, and then toggle between white and gray painters.
        while ((end = text.indexOf('\n', start)) >= 0) {
            even = !even;
            DefaultHighlightPainter painter = even ? grayPainter : whitePainter;
            hilite.addHighlight(start, end+1, painter);
            start = end+1;
        }
    } catch (BadLocationException e) {
        e.printStackTrace();
    }

    JPanel p = new JPanel(new BorderLayout());      
    p.add(t, BorderLayout.CENTER);
    JFrame f = new JFrame();
    f.add(p);
    f.setSize(100, 100);
    f.setVisible(true);
}

这里是VonC的MyHighlighter

class MyHighlighter extends DefaultHighlighter
{

    private JTextComponent component;

    /**
     * @see javax.swing.text.DefaultHighlighter#install(javax.swing.text.JTextComponent)
     */
    @Override
    public final void install(final JTextComponent c)
    {
        super.install(c);
        this.component = c;
    }

    /**
     * @see javax.swing.text.DefaultHighlighter#deinstall(javax.swing.text.JTextComponent)
     */
    @Override
    public final void deinstall(final JTextComponent c)
    {
        super.deinstall(c);
        this.component = null;
    }

    /**
     * Same algo, except width is not modified with the insets.
     * 
     * @see javax.swing.text.DefaultHighlighter#paint(java.awt.Graphics)
     */
    @Override
    public final void paint(final Graphics g)
    {
        final Highlighter.Highlight[] highlights = getHighlights();
        final int len = highlights.length;
        for (int i = 0; i < len; i++)
        {
            Highlighter.Highlight info = highlights[i];
            if (info.getClass().getName().indexOf("LayeredHighlightInfo") > -1)
            {
                // Avoid allocing unless we need it.
                final Rectangle a = this.component.getBounds();
                final Insets insets = this.component.getInsets();
                a.x = insets.left;
                a.y = insets.top;
                // a.width -= insets.left + insets.right + 100;
                a.height -= insets.top + insets.bottom;
                for (; i < len; i++)
                {
                    info = highlights[i];
                    if (info.getClass().getName().indexOf(
                            "LayeredHighlightInfo") > -1)
                    {
                        final Highlighter.HighlightPainter p = info
                                .getPainter();
                        p.paint(g, info.getStartOffset(), info
                                .getEndOffset(), a, this.component);
                    }
                }
            }
        }
    }
}

1

这里是一个可能解决方案的示例

简单解释一下,JTextPane是一个样式文档编辑器,因此允许更改StyledDocument,也就是包含样式信息(例如给定行的背景颜色)的文档。


0
JTextField someField = new JTextField();
someField.setBackground(Color.GREY );

抱歉,我是指JTextPane而不是JTextField... 我已经更正了问题。 - jumar
不幸的是,这将更改整个 JTextPane 的颜色,而不仅仅是其中一行。 - Riduidel
@Riduidel,是的,但从最初的措辞来看,这是有道理的。 - jzd

0
我尝试通过重载paintComponent()方法并根据组件高度和字体大小手动绘制背景来实现这一点,但我没有成功。
听起来很合理。确保使文本窗格不透明。
然后基本代码如下:
1. 根据剪辑区域绘制交替背景 2. 调用super.paintComponent(),以便文本在顶部绘制。
如果需要更多帮助,请发布SSCCE演示问题。

-1
JTextPane可以将HTML文档作为文本进行处理。您是否考虑通过HTML文档将文本添加到JTextPane中?
JTextPane pane = new JTextPane();
pane.setContentType("text/html");

String text = /*some html table or set of divs for formatting */

pane.setText(text);

myJFrame.add(pane);

当您构建文本字符串时,可以使用CSS设置交替颜色,或直接将其硬编码到创建的文档中。这将帮助您避免覆盖重绘方法。

在不允许用户编辑框(即将setEditable设置为false)的情况下,这将起作用良好。如果您希望每次用户按Enter键时都重新绘制该行,则必须调整解决方案。


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