JTextPane突出显示问题 [英] JTextPane highlighting issue

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

问题描述

我一直试图在小文本编辑器中实现突出显示功能的最后几天。出于某种原因,我得到一个奇怪的结果:

The last days I have been trying to implement a highlighting feature in a small text editor. For some reason I get a strange result:

给定的例子应该突出显示每个dolor - 第一次出现的是正确找到并突出显示但下一次出现并没有。

The given example should highlight each "dolor" - the first occurences are correctly found and highlighted but the next ones aren't.

这是我到目前为止编写的代码:

Here is the code I wrote so far:

import java.awt.Color;
import java.awt.Dimension;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;

import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextPane;
import javax.swing.text.BadLocationException;
import javax.swing.text.DefaultHighlighter;
import javax.swing.text.DefaultHighlighter.DefaultHighlightPainter;
import javax.swing.text.DefaultStyledDocument;

/**
 * Highlighting created on 04.11.2013<br>
 * <br>
 * Specification:<br>
 */
public class Highlighting extends JFrame implements MouseListener {

    private JScrollPane scrollPane;
    private JTextPane textPane;

    private DefaultHighlighter highlighter;
    private DefaultHighlightPainter painter;

    public static void main(String[] args) {
        new Highlighting().setVisible(true);
    }

    /**
     * 
     */
    public Highlighting() {
        this.initialize();
        this.build();
        this.configure();
    }

    /**
     *
     */
    public void initialize() {
        this.scrollPane = new JScrollPane();
        this.textPane = new JTextPane();
        this.highlighter = new DefaultHighlighter();
        this.painter = new DefaultHighlightPainter(Color.RED);
    }

    /**
     *
     */
    public void build() {
        this.add(this.scrollPane);
    }

    /**
     *
     */
    public void configure() {
        this.scrollPane.setViewportView(this.textPane);
        this.textPane.setHighlighter(this.highlighter);
        this.textPane.addMouseListener(this);
        this.textPane.setDocument(new DefaultStyledDocument());

        this.setPreferredSize(new Dimension(400, 500));
        this.pack();
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }

    /**
     * 
     */
    private void highlight() {
        this.highlighter.removeAllHighlights();

        String selectedText = this.textPane.getSelectedText();
        String text = this.textPane.getText();

        int wordlength = selectedText.length();

        int index = 0;
        while ((index = text.indexOf(selectedText, index)) != -1) {

            try {
                this.highlighter.addHighlight(index, index + wordlength, this.painter);
            } catch (BadLocationException e) {
                e.printStackTrace();
            }

            index += wordlength;
        }
    }

    @Override
    public void mouseClicked(MouseEvent e) {
        if (e.getClickCount() == 2) {
            this.highlight();
        }
    }

    @Override
    public void mousePressed(MouseEvent e) {}

    @Override
    public void mouseReleased(MouseEvent e) {}

    @Override
    public void mouseEntered(MouseEvent e) {}

    @Override
    public void mouseExited(MouseEvent e) {}

}

这是否与行分隔符有关( \\\\ n )?

Does this has something to do with the line separators (\r\n) ?

推荐答案

A JTextComponent getText()和A JTextPane / JEditorPane 's getText()具有不同的实现。 JTextPane / JEditorPane 使用 EditorKit 将文档内容(文本)写入 StringWriter 然后返回带格式的文本并在文档中插入行/段落。但 JTextCompoent 直接返回文档内容:

A JTextComponent's getText() and A JTextPane/JEditorPane's getText() has different implementation. JTextPane/JEditorPane uses EditorKit to write the document content(text) to a StringWriter and then return the text with formatting and inserting a line/paragraph break into the document. But the JTextCompoent returns document content directly by:

document.getText(0, document.getLength());

如果你试图比较长度,你会更好地理解: jTextPane1.getText ()。length() jTextPane1()。getDocument()。getLength()

You will better understand if you try to compare the length : jTextPane1.getText().length() and jTextPane1().getDocument().getLength().

通过插入以下字符串来重现差异

DefaultStyleDocument.insertString(0, str, primaryStyle)

when str = "I\n not"   ; document length = 6, getText().length = 7
when str = "I\r\n not" ; document length = 7, getText().length = 8
when str = "I\n\n not" ; document length = 7, getText().length = 9!

因此,在高亮度文本程序中尝试使用以下方式阅读内容文本:

So, in your high-lighting text program try reading the content text using:

DefaultStyledDocument document = (DefaultStyledDocument) jTextPane1.getDocument();
try {
    contText = document.getText(0, document.getLength());
} catch (BadLocationException ex) {
     Logger.getLogger(JTextPaneTest.class.getName()).log(Level.SEVERE, null, ex);
 }

然后在 contText中搜索您选择的文本位置正如你所做的那样,你应该好好去。因为 highlighter.addHighlight(int p0,int p1,Highlighter.HighlightPainter p)使用文档进行位置偏移。

Then search for your selected text position in the contText as you were doing and you should be good to go. Because, highlighter.addHighlight(int p0, int p1, Highlighter.HighlightPainter p) uses the document for position offset.

使用 CaretListener

Use CaretListener:

要突出显示文本选择,最好使用 CaretListener ,根本不需要添加鼠标和键盘选择处理代码:

To Highlight upon text selection, It is better to use CaretListener, no need to add mouse and key board selection handling code at all:

jTextPane1.addCaretListener(new CaretListener() {
        public void caretUpdate(CaretEvent evt) {
            if(evt.getDot() == evt.getMark())return;

    JTextPane txtPane = (JTextPane) evt.getSource();
    DefaultHighlighter highlighter = (DefaultHighlighter) txtPane.getHighlighter();
    highlighter.removeAllHighlights();
    DefaultHighlightPainter hPainter = new DefaultHighlightPainter(new Color(0xFFAA00));
    String selText = txtPane.getSelectedText();
    String contText = "";// = jTextPane1.getText();

    DefaultStyledDocument document = (DefaultStyledDocument) txtPane.getDocument();

    try {
        contText = document.getText(0, document.getLength());
    } catch (BadLocationException ex) {
        Logger.getLogger(JTextPaneTest.class.getName()).log(Level.SEVERE, null, ex);
    }

    int index = 0;

    while((index = contText.indexOf(selText, index)) > -1){

        try {
            highlighter.addHighlight(index, selText.length()+index, hPainter);
            index = index + selText.length();
        } catch (BadLocationException ex) {
            Logger.getLogger(JTextPaneTest.class.getName()).log(Level.SEVERE, null, ex);
           //System.out.println(index);
        }
       }
        }
    });

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

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