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

Posted

技术标签:

【中文标题】如何在 JTextPane 中的一行上设置自定义背景颜色【英文标题】:How to set a custom background color on a line in a JTextPane 【发布时间】:2011-06-07 22:19:11 【问题描述】:

我想从我的 JTextPane 的一行到下一行在灰色和白色之间交替作为背景。 我试图通过重载paintComponent()方法并根据组件高度和字体大小手动绘制背景来做到这一点,但我没有成功。

有什么提示吗?

【问题讨论】:

“一行”是什么意思?如果您交替使用您使用的颜色,setBackground() 会不起作用吗? 您的文本窗格是否可编辑?即,如果添加/删除线条,您是否希望背景改变? 【参考方案1】:

您可以使用由@VonC 编写的行高亮器(here 或here)来响应this question。

为了突出显示交替行,您可以按如下方式使用它:

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

【讨论】:

【参考方案2】:

这里是an example 一个可能的解决方案。

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

【讨论】:

【参考方案3】:
JTextField someField = new JTextField();
someField.setBackground(Color.GREY );

【讨论】:

对不起,我的意思是 JTextPane 不是 JTextField...我已经更正了这个问题。 不幸的是,这会改变整个 JTextPane 颜色,而不仅仅是其中的一行。 @Riduidel,是的,但是这个问题最初的措辞是有道理的。【参考方案4】:

我试图通过重载paintComponent()方法并根据组件高度和字体大小手动绘制背景来做到这一点,但我没有成功。

听起来很合理。确保使文本窗格不透明。

那么基本代码是:

    根据剪辑区域绘制交替背景 调用 super.paintComponent() 以便将文本绘制在背景之上。

如果您需要更多帮助,请发布 SSCCE 来演示问题。

【讨论】:

【参考方案5】:

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)

【讨论】:

以上是关于如何在 JTextPane 中的一行上设置自定义背景颜色的主要内容,如果未能解决你的问题,请参考以下文章

如何在 JTextPane 中为文本和下划线设置不同的颜色?

Steam优化Xbox手柄体验 支持绑定背键及分享键自定义设置

JTextPane:如何设置字体大小

。如何在多个jtextpanes上传播我的文字?

如何使用 Java 代码查看 JTextPane 中的段落符号?

如何防止 JTextPane.setCaretPosition(int) 中的内存泄漏?