JTextPane突出显示问题

Mar*_*kus 2 java swing highlighting jtextpane swing-highlighter

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

在此输入图像描述

给出的例子应该突出显示每个"dolor" - 第一次出现是正确找到并突出显示但下一次出现并未突出显示.

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

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

}
Run Code Online (Sandbox Code Playgroud)

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

Sag*_*age 9

JTextComponentgetText()和A JTextPane/JEditorPanegetText()有不同的实现.JTextPane/JEditorPane用于EditorKit将文档内容(文本)写入a StringWriter,然后返回带有格式的文本并在文档中插入行/段落.但是JTextCompoent返回文档内容直接由:

document.getText(0, document.getLength());
Run Code Online (Sandbox Code Playgroud)

如果你试图比较长度,你会更好地理解:jTextPane1.getText().length()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!
Run Code Online (Sandbox Code Playgroud)

因此,在您的高亮度文本程序中尝试使用以下内容读取内容文本:

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);
 }
Run Code Online (Sandbox Code Playgroud)

然后在contText你正在做的事情中搜索你选择的文本位置,你应该很高兴.因为,highlighter.addHighlight(int p0, int p1, Highlighter.HighlightPainter p)使用documentfor position offset.

用途CaretListener:

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

在此输入图像描述

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);
        }
       }
        }
    });
Run Code Online (Sandbox Code Playgroud)