很抱歉要问这个问题,因为还有一些关于同一主题的帖子,但我还是没有设法为我的问题应用这些解决方案。
简单的场景。我有一个JTextPane
,我有一个搜索方法。它检测所有匹配的单词并将其突出显示为灰色为了浏览不同的比赛,我有第二个荧光笔,突出显示当前"活跃"匹配红色。按下按钮,活动突出显示进入下一个匹配。 (基本上chromes搜索是如何工作的)
除了移除旧的活动荧光笔外,一切正常。有一个名为.removeHighlight()
的方法,我需要删除旧的高亮,但无论我作为参数插入什么,我都会得到异常或没有任何反应。我会使用.removeAllHighlights()
,但因为我有其他亮点(突出显示所有命中灰色)我会松开它们,所以我只需删除最后一个活动突出显示。
官方oracle文档用removeHighlight(hilites[i])
做了一些事情,但说实话,我不知道那里发生了什么。
到目前为止我已经得到的代码:
private DefaultHighlightPainter highlightOne = new DefaultHighlightPainter(Color.RED);
private Object last;
public void paintAt(int pos){
try {
if (last != null){
motherFrame.tField.getHighlighter().removeHighlight(last);
}
last = motherFrame.tField.getHighlighter().addHighlight(pos, pos + searchWordLength, highlightOne);
} catch (BadLocationException e) {
//TODO
}
}
这里有一张照片:
更新 这是一个可运行的:(对不起凌乱的代码。)
http://hostcode.sourceforge.net/view/2563 和 http://hostcode.sourceforge.net/view/2564
答案 0 :(得分:2)
Highlighter#addHighlight
会返回一个代表当前突出显示的Object
标记。调用Highlighter#removeHighlight
时应该使用此标记,我认为这意味着您可以使用HighlightPainter
的相同实例来突出显示文档的多个部分,但仍然可以单独管理它们,例如..
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.JTextPane;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.text.BadLocationException;
import javax.swing.text.DefaultHighlighter;
import javax.swing.text.Document;
public class TestEditorPane01 {
public static void main(String[] args) {
new TestEditorPane01();
}
public TestEditorPane01() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new EditorPane());
frame.setSize(400, 400);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class EditorPane extends JPanel {
private JTextPane editor = new JTextPane();
private int lastMatch;
private String find = "Method";
private DefaultHighlighter.DefaultHighlightPainter highlightPainter;
private Object highlightTag;
private JTextField searchField;
private JButton searchButton;
public EditorPane() {
setLayout(new BorderLayout());
editor = new JTextPane();
try (FileReader reader = new FileReader(new File("/some file.txt"))) {
editor.read(reader, "script");
} catch (IOException exp) {
exp.printStackTrace();
}
add(new JScrollPane(editor));
JPanel searchPane = new JPanel(new GridBagLayout());
searchField = new JTextField(10);
searchButton = new JButton("Search");
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 0;
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.weightx = 1;
searchPane.add(searchField, gbc);
gbc.gridx++;
gbc.fill = GridBagConstraints.NONE;
gbc.weightx = 0;
searchPane.add(searchButton, gbc);
searchButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
String text = searchField.getText();
if (!text.equals(find)) {
find = text;
lastMatch = 0;
}
highlightNext();
}
});
add(searchPane, BorderLayout.SOUTH);
}
public void highlightNext() {
Document document = editor.getDocument();
try {
if (lastMatch + find.length() >= document.getLength()) {
lastMatch = 0;
}
for (; lastMatch + find.length() < document.getLength(); lastMatch++) {
String match = document.getText(lastMatch, find.length());
if (find.equalsIgnoreCase(match)) {
if (highlightTag != null) {
editor.getHighlighter().removeHighlight(highlightTag);
}
if (highlightPainter == null) {
highlightPainter = new javax.swing.text.DefaultHighlighter.DefaultHighlightPainter(Color.YELLOW);
}
highlightTag = editor.getHighlighter().addHighlight(lastMatch, lastMatch + find.length(), highlightPainter);
Rectangle viewRect = editor.modelToView(lastMatch);
editor.scrollRectToVisible(viewRect);
lastMatch += find.length();
break;
}
}
} catch (BadLocationException ex) {
ex.printStackTrace();
}
}
}
}
由于您正在执行此操作,并且它无法正常工作,因此这表明您的代码存在其他问题,这在您提供的代码段中并不明显。考虑提供一个runnable example来证明您的问题。这将减少混淆和更好的响应
<强>更新... 强>
SearchDialog
确实不需要了解TestFrame
,所有它感兴趣的是JTextComponent
... addHighlight
的结果分配给last
?? null
布局...... 当我最终得到您的示例代码进行编译时,这就是我所呈现的......
......好的,我想,我只是扩大窗口......
......好吧,有一个问题......我没有时间解决。
避免使用null
布局,像素完美布局是现代ui设计中的一种幻觉。影响组件个体大小的因素太多,您无法控制。 Swing旨在与布局管理器一起工作,放弃这些将导致问题和问题的终结,您将花费越来越多的时间来纠正
请查看Why is it frowned upon to use a null layout in SWING?了解更多详情......
答案 1 :(得分:0)
感谢MadProgrammer,我发现了问题所在:
原始问题&#34; 如何删除旧荧光笔&#34;答案很简单: 这是我发布的示例代码。
private DefaultHighlightPainter highlightOne = new DefaultHighlightPainter(Color.RED);
private Object last;
public void paintAt(int pos){
try {
if (last != null){
textPane.getHighlighter().removeHighlight(last);
}
last = textPane.getHighlighter().addHighlight(pos, pos + searchWordLength, highlightOne);
} catch (BadLocationException e) {
//TODO
}
}
(因为我有两个荧光笔,第一个覆盖了第二个荧光笔,所以第二个没有显示出来。这就是为什么我认为我的代码无效。)
更新问题&#34; 如何处理多个荧光笔&#34;答案也很简单。人们必须知道的事情只有一个问题。来自荧光笔的油漆不会被其他后来调用的荧光笔过度涂漆。所以基本上我不得不颠倒调用荧光笔的顺序。 看起来像这样:
textPane.getHighlighter().removeAllHighlights();
textPane.getHighlighter().addHighlight(pos, pos + searchWordLength, red);
for int i = 0; i < matchList.size(); i++){
int position = matchList.get(i);
textPane.getHighlighter().addHighlight(position, possition + searchWordLength, grey);
}
这不是最佳解决方案,因为您必须在每次更改时重新绘制每个荧光笔。但是人们可以通过delta-change-draw来优化它(仅重绘已更改的部分)。