突出显示JTextPane中的当前行 [英] Highlight current row in JTextPane

查看:119
本文介绍了突出显示JTextPane中的当前行的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm trying for more than 2 days to implement a specific requirement for a text editor window... unfortunately without success so far :(

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

The goal is to get a text editor window which will highlight the current row, like other text editors do. With current row I mean the row where currently the cursor/caret is positioned.

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

I already found two different approaches but unfortunately I'm not able to adopt them so they work as expected.

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

The first approach is to overwrite the DefaultHighlighter (http://snippets.dzone.com/posts/show/6688). In the second approach the HighlighterPainter will be overwritten instead (http://www.jroller.com/santhosh/date/20050622).

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

Right now I'm trying to adopt the first approach in my project but as I said it is not working as desired.

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

At the end of this post I'm posting a small sample application which demonstrates the problem.


  • 如果我启动程序,则将插入符号放在第一行的开头。但是,该行不会突出显示。

  • 现在我输入一些字符。这些字符将突出显示,但那些字符不是完整的行

  • 我按Enter键移动到下一行。第一行不再突出显示正确的内容。第二行也没有突出显示,这是不正确的。再次,当我键入一些字符时,那些将被突出显示而不是完整的行。

  • 当我现在将插入符号移回第一行时,通过向上键或鼠标单击,完整的第一行将突出显示,而不仅仅是现有的字符。这是我从一开始就想要的行为。

  • If I start the program, the caret is placed at the beginning of the first line. However, the line is not highlighted.
  • Now I type in some characters. Those chars will be highlighted but only those chars not the complete line
  • I hit enter to move to the next line. The first line is not highlighted anymore what is correct. The second line isn't highlighted as well, what is not correct. Again, when I type in some chars, those will be higlighted but not the complete row.
  • When I now move back the caret to the first line, either by cursor up key or mouse clicking, the complete first line will be highlighted, not only the existing chars. This is the behavior I want right from the start.

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

I hope anybody can tell me what I'm doing wrong here... or explain why it is not possible to resolve that issue at all. Any alternative solutions how I could realize the line highlighting are also highly appreciated!

非常感谢提前
干杯
Preachie

Thanks a lot in advance 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();
        }
    }
}


推荐答案

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

我认为这就是你要找的东西。我拿了那个 LinePainter 类并将你的构造函数复制到一个main方法中,拿出你的荧光笔部分并添加一个新的LinePainter(textPane); 像魅力一样工作

I think this is what you are looking for. I took that LinePainter class and copied your constructor over into a main method, took out your highlighter parts and added a new LinePainter(textPane); Works like a charm

这篇关于突出显示JTextPane中的当前行的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆