我一直试图在小文本编辑器中实现突出显示功能的最后几天。出于某种原因,我得到了一个奇怪的结果:
给定的例子应该突出显示每个“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) {}
}
这是否与行分隔符(\r\n
)有关?
答案 0 :(得分:9)
JTextComponent
的{{1}}和A getText()
的{{1}}具有不同的实施方式。 JTextPane/JEditorPane
使用getText()
将文档内容(文本)写入JTextPane/JEditorPane
,然后返回带格式的文本并在文档中插入行/段落。但EditorKit
直接通过以下方式返回文档内容:
StringWriter
如果您尝试比较长度:JTextCompoent
和document.getText(0, document.getLength());
,您会更好地理解。
通过插入字符串:
来重现差异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!
中搜索您选择的文字位置,你应该好好去。因为,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)
:
要突出显示文本选择,最好使用document
,根本不需要添加鼠标和键盘选择处理代码:
CaretListener
答案 1 :(得分:3)
如何删除荧光笔highlighter.removeHighlight(h);
View.modelToView
新荧光笔
注意我不知道如何确定new line \n
内部选择,不能从此代码
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.awt.Shape;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.JTextPane;
import javax.swing.UIManager;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.text.BadLocationException;
import javax.swing.text.DefaultHighlighter;
import javax.swing.text.Document;
import javax.swing.text.Highlighter;
import javax.swing.text.JTextComponent;
import javax.swing.text.LayeredHighlighter;
import javax.swing.text.Position;
import javax.swing.text.View;
public class HighlightExample {
private JFrame f = new JFrame("Highlight example");
private JPanel panel = new JPanel();
private JTextPane textPane = new JTextPane();
private JTextField tf = new JTextField("wrapping!");
private String word;
private Highlighter highlighter = new UnderlineHighlighter(null);
public HighlightExample() {
textPane.setHighlighter(highlighter);
textPane.setText("This text pane contains no html. It supports letter wrapping, "
+ "\nThis text pane contains no html. It supports letter wrapping!, "
+ "\nThis text pane contains no html. It supports letter wrapping?, "
+ "\nThis text pane contains no html. It supports letter wrapping-, "
+ "\nThis text pane contains no html. It supports letter wrapping!, "
+ "\nThis text pane contains no html. It supports letter wrapping_, "
+ "\nThis text pane contains no html. It supports letter wrapping!, "
+ "\nThis text pane contains no html. It supports letter wrapping?, "
+ "\nThis text pane contains no html. It supports letter wrapping!, "
+ "\nThis text pane contains no html. It supports letter wrapping, "
+ "\nThis text pane contains no html. It supports letter wrapping!, "
+ "\nThis text pane contains no html. It supports letter wrapping-, "
+ "\nThis text pane contains no html. It supports letter wrapping!, "
+ "\nThis text pane contains no html. It supports letter wrapping?");
panel.setLayout(new BorderLayout());
panel.add(new JLabel("Enter word, then press ENTER key: "), "West");
panel.add(tf, "Center");
/*try {
textPane.read(new FileReader("links1.html"), null);
} catch (Exception e) {
System.out.println("Failed to load file " + args[0]);
System.out.println(e);
}*/
final WordSearcher searcher = new WordSearcher(textPane);
tf.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent evt) {
word = tf.getText().trim();
int offset = searcher.search(word);
if (offset != -1) {
try {
textPane.scrollRectToVisible(textPane
.modelToView(offset));
} catch (BadLocationException e) {
}
}
}
});
textPane.getDocument().addDocumentListener(new DocumentListener() {
@Override
public void insertUpdate(DocumentEvent evt) {
searcher.search(word);
}
@Override
public void removeUpdate(DocumentEvent evt) {
searcher.search(word);
}
@Override
public void changedUpdate(DocumentEvent evt) {
}
});
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(panel, "South");
f.add(new JScrollPane(textPane), "Center");
f.setSize(400, 400);
f.setVisible(true);
}
public static void main(String[] args) {
UIManager.put("TextPane.caretForeground", Color.yellow);
UIManager.put("TextPane.selectionBackground", Color.green);
UIManager.put("TextPane.selectionForeground", Color.blue);
/*try {
UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
} catch (Exception evt) {
}*/
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
new HighlightExample();
}
});
}
}
// A simple class that searches for a word in
// a document and highlights occurrences of that word
class WordSearcher {
protected JTextComponent comp;
protected Highlighter.HighlightPainter painter;
public WordSearcher(JTextComponent comp) {
this.comp = comp;
this.painter = new UnderlineHighlighter.UnderlineHighlightPainter(Color.red);
}
// Search for a word and return the offset of the first occurrence.
// Highlights are added for all occurrences found.
public int search(String word) {
int firstOffset = -1;
Highlighter highlighter = comp.getHighlighter();
// Remove any existing highlights for last word
Highlighter.Highlight[] highlights = highlighter.getHighlights();
for (int i = 0; i < highlights.length; i++) {
Highlighter.Highlight h = highlights[i];
if (h.getPainter() instanceof UnderlineHighlighter.UnderlineHighlightPainter) {
highlighter.removeHighlight(h);
}
}
if (word == null || word.equals("")) {
return -1;
}
String content = null; // Look for the word we are given - insensitive search
try {
Document d = comp.getDocument();
content = d.getText(0, d.getLength()).toLowerCase();
} catch (BadLocationException e) {
return -1; // Cannot happen
}
word = word.toLowerCase();
int lastIndex = 0;
int wordSize = word.length();
while ((lastIndex = content.indexOf(word, lastIndex)) != -1) {
int endIndex = lastIndex + wordSize;
try {
highlighter.addHighlight(lastIndex, endIndex, painter);
} catch (BadLocationException e) {
// Nothing to do
}
if (firstOffset == -1) {
firstOffset = lastIndex;
}
lastIndex = endIndex;
}
return firstOffset;
}
}
class UnderlineHighlighter extends DefaultHighlighter {
protected static final Highlighter.HighlightPainter sharedPainter = new UnderlineHighlightPainter(null);// Shared painter used for default highlighting
protected Highlighter.HighlightPainter painter; // Painter used for this highlighter
public UnderlineHighlighter(Color c) {
painter = (c == null ? sharedPainter : new UnderlineHighlightPainter(c));
}
// Convenience method to add a highlight with the default painter.
public Object addHighlight(int p0, int p1) throws BadLocationException {
return addHighlight(p0, p1, painter);
}
@Override
public void setDrawsLayeredHighlights(boolean newValue) {
if (newValue == false) {// Illegal if false - we only support layered highlights
throw new IllegalArgumentException(
"UnderlineHighlighter only draws layered highlights");
}
super.setDrawsLayeredHighlights(true);
}
// Painter for underlined highlights
public static class UnderlineHighlightPainter extends LayeredHighlighter.LayerPainter {
protected Color color; // The color for the underline
public UnderlineHighlightPainter(Color c) {
color = c;
}
@Override
public void paint(Graphics g, int offs0, int offs1, Shape bounds,
JTextComponent c) {// Do nothing: this method will never be called
}
@Override
public Shape paintLayer(Graphics g, int offs0, int offs1, Shape bounds,
JTextComponent c, View view) {
g.setColor(color == null ? c.getSelectionColor() : color);
Rectangle alloc = null;
if (offs0 == view.getStartOffset() && offs1 == view.getEndOffset()) {
if (bounds instanceof Rectangle) {
alloc = (Rectangle) bounds;
} else {
alloc = bounds.getBounds();
}
} else {
try {
Shape shape = view.modelToView(offs0, Position.Bias.Forward, offs1,
Position.Bias.Backward, bounds);
alloc = (shape instanceof Rectangle) ? (Rectangle) shape : shape.getBounds();
} catch (BadLocationException e) {
return null;
}
}
FontMetrics fm = c.getFontMetrics(c.getFont());
int baseline = alloc.y + alloc.height - fm.getDescent() + 1;
g.drawLine(alloc.x, baseline, alloc.x + alloc.width, baseline);
g.drawLine(alloc.x, baseline + 1, alloc.x + alloc.width, baseline + 1);
return alloc;
}
}
}