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

时间:2023-01-27 16:38:37

I would like to alternate between gray and white as background from one line of my JTextPane to the next. I tried to do this by overloading the paintComponent() method and drawing the background manually according to component height an Font size but I did not succeed.

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

Any hints?

任何提示?

5 个解决方案

#1


2  

You can use the line highlighter (here or here), written by @VonC, in response to this question.

您可以使用@VonC编写的行高亮显示(此处或此处)来回答此问题。

In order to highlight alternate lines you can use it as follows:

为了突出显示备用线,您可以按如下方式使用它:

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

Here is VonC's MyHighlighter:

这是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


1  

Here is an example of a possible solution.

以下是可能解决方案的示例。

To explain it a little, JTextPane is a styled document editor, and as such, allows one to change StyledDocument, that's to say a document which includes style information, like the background color for a given line.

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

#3


0  

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

#4


0  

I tried to do this by overloading the paintComponent() method and drawing the background manually according to component height an Font size but I did not succeed.

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

Sounds reasonable. Make sure you make the text pane non-opaque.

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

Then the basic code would be:

那么基本代码将是:

  1. paint your alternating background based on the clip region
  2. 根据剪辑区域绘制交替背景
  3. invoke super.paintComponent() so the text is painted over top of the background.
  4. 调用super.paintComponent(),以便将文本绘制在背景的顶部。

If you need more help then post the SSCCE demonstrating the problem.

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

#5


-1  

JTextPane will take an HTML document as text. Have you considered adding your text to the JTextPane via an HTML document?

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

When you build the text string, you can set the alternating colors with css, or hard code it directly into you created document. This will help you avoid having to override the repaint methods.

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

This will work good in instances where you will not allow the user to edit the box (ie setEditable to false) If you expect this to repaint the line each time the user hits the enter key, you will have to adapt the solution

这将在您不允许用户编辑框的情况下工作(即setEditable为false)如果您希望每次用户点击回车键时重新绘制该行,您将不得不调整解决方案

#1


2  

You can use the line highlighter (here or here), written by @VonC, in response to this question.

您可以使用@VonC编写的行高亮显示(此处或此处)来回答此问题。

In order to highlight alternate lines you can use it as follows:

为了突出显示备用线,您可以按如下方式使用它:

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

Here is VonC's MyHighlighter:

这是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


1  

Here is an example of a possible solution.

以下是可能解决方案的示例。

To explain it a little, JTextPane is a styled document editor, and as such, allows one to change StyledDocument, that's to say a document which includes style information, like the background color for a given line.

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

#3


0  

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

#4


0  

I tried to do this by overloading the paintComponent() method and drawing the background manually according to component height an Font size but I did not succeed.

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

Sounds reasonable. Make sure you make the text pane non-opaque.

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

Then the basic code would be:

那么基本代码将是:

  1. paint your alternating background based on the clip region
  2. 根据剪辑区域绘制交替背景
  3. invoke super.paintComponent() so the text is painted over top of the background.
  4. 调用super.paintComponent(),以便将文本绘制在背景的顶部。

If you need more help then post the SSCCE demonstrating the problem.

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

#5


-1  

JTextPane will take an HTML document as text. Have you considered adding your text to the JTextPane via an HTML document?

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

When you build the text string, you can set the alternating colors with css, or hard code it directly into you created document. This will help you avoid having to override the repaint methods.

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

This will work good in instances where you will not allow the user to edit the box (ie setEditable to false) If you expect this to repaint the line each time the user hits the enter key, you will have to adapt the solution

这将在您不允许用户编辑框的情况下工作(即setEditable为false)如果您希望每次用户点击回车键时重新绘制该行,您将不得不调整解决方案