突出显示JTextPane中的当前行

Pre*_*hie 9 java swing highlighting jtextpane

我正在尝试超过2天来实现文本编辑器窗口的特定要求...不幸的是到目前为止没有成功:(

目标是获得一个文本编辑器窗口,该窗口将突出显示当前行,就像其他文本编辑器一样.对于当前行,我指的是当前光标/插入符所在的行.

我已经找到了两种不同的方法,但不幸的是我无法采用它们,所以它们按预期工作.

第一种方法是覆盖DefaultHighlighter(http://snippets.dzone.com/posts/show/6688).在第二种方法中,HighlighterPainter将被覆盖(http://www.jroller.com/santhosh/date/20050622).

现在我正在尝试在我的项目中采用第一种方法,但正如我所说,它没有按预期工作.

在这篇文章的最后,我发布了一个小样本应用程序来演示这个问题.

  • 如果我启动程序,则将插入符号放在第一行的开头.但是,该行未突出显示.
  • 现在我输入一些字符.这些字符将突出显示,但只有那些字符不完整
  • 我点击Enter进入下一行.第一行不再突出显示正确的内容.第二行也没有突出显示,这是不正确的.再次,当我键入一些字符时,那些将是高亮显示但不是完整的行.
  • 当我现在将插入符号移回第一行时,通过向上键或鼠标单击,将突出显示完整的第一行,而不仅仅是现有的字符.这是我从一开始就想要的行为.

我希望有人能告诉我这里我做错了什么......或者解释为什么根本无法解决这个问题.如何实现线条突出显示的任何替代解决方案也非常感谢!

非常感谢Cheers Preachie

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Insets;
import java.awt.Rectangle;

import javax.swing.JFrame;
import javax.swing.JTextPane;
import javax.swing.event.CaretEvent;
import javax.swing.event.CaretListener;
import javax.swing.text.DefaultHighlighter;
import javax.swing.text.Highlighter;
import javax.swing.text.JTextComponent;

public class HighlightProblem extends JFrame {
    private static final long serialVersionUID = 1L;
    private final JTextPane textPane;
    private final Highlighter.HighlightPainter cyanPainter;

    public HighlightProblem() {
        cyanPainter = new DefaultHighlighter.DefaultHighlightPainter(Color.CYAN);

        textPane = new JTextPane();
        textPane.setPreferredSize(new Dimension(500, 300));
        textPane.setHighlighter(new LineHighlighter());
        textPane.addCaretListener(new CaretListener() {
            @Override
            public void caretUpdate(CaretEvent e) {
                setHighlight(e);
            }
        });
        getContentPane().add(textPane);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        pack();
        setVisible(true);
    }

    public static void main(String[] args) {
        new HighlightProblem();
    }

    public void setHighlight(CaretEvent e) {
        textPane.getHighlighter().removeAllHighlights();
        int currentLine = getLineFromOffset(textPane, e.getDot());
        int startPos = getLineStartOffsetForLine(textPane, currentLine);
        int endOffset = getLineEndOffsetForLine(textPane, currentLine);

        try {
            textPane.getHighlighter().addHighlight(startPos, endOffset, cyanPainter);           
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        textPane.repaint();
    }

    public int getLineFromOffset(JTextComponent component, int offset) {
        return component.getDocument().getDefaultRootElement().getElementIndex(offset);
    }

    public int getLineStartOffsetForLine(JTextComponent component, int line) {
        return component.getDocument().getDefaultRootElement().getElement(line).getStartOffset();
    }

    public int getLineEndOffsetForLine(JTextComponent component, int line) {
        return component.getDocument().getDefaultRootElement().getElement(line).getEndOffset();
    }

    public class LineHighlighter extends DefaultHighlighter {
        private JTextComponent component;

        @Override
        public final void install(final JTextComponent c) {
            super.install(c);
            this.component = c;
        }

        @Override
        public final void deinstall(final JTextComponent c) {
            super.deinstall(c);
            this.component = null;
        }

        @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;
                    final Highlighter.HighlightPainter p = info.getPainter();
                    p.paint(g, info.getStartOffset(), info.getEndOffset(), a, this.component);
                }
            }
        }

        @Override
        public void removeAllHighlights() {
            textPane.repaint(0, 0, textPane.getWidth(), textPane.getHeight());
            super.removeAllHighlights();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

spe*_*sal 4

http://tips4java.wordpress.com/2008/10/29/line-painter/

我想这就是您正在寻找的。我拿了那个LinePainter类并将你的构造函数复制到主方法中,取出你的荧光笔部分并添加了一个new LinePainter(textPane); 像魅力一样的 Works