Java删除旧的突出显示

时间:2014-11-05 20:04:26

标签: java swing highlight

很抱歉要问这个问题,因为还有一些关于同一主题的帖子,但我还是没有设法为我的问题应用这些解决方案。

简单的场景。我有一个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
    }
}  

这里有一张照片:

enter image description here

更新 这是一个可运行的:(对不起凌乱的代码。)

http://hostcode.sourceforge.net/view/2563http://hostcode.sourceforge.net/view/2564

2 个答案:

答案 0 :(得分:2)

Highlighter#addHighlight会返回一个代表当前突出显示的Object标记。调用Highlighter#removeHighlight时应该使用此标记,我认为这意味着您可以使用HighlightPainter的相同实例来突出显示文档的多个部分,但仍然可以单独管理它们,例如..

Highlight

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来证明您的问题。这将减少混淆和更好的响应

<强>更新...

  1. 不要将您的示例代码链接到外部网站,不是每个人都可以访问外部网站,或者无论如何都可能无法关注链接......
  2. 可运行的示例应该是自包含的,不依赖于其他库或资源,如图标,应该包含在单个文件中
  3. 不要不必要地暴露您的UI组件,也就是说,我认为SearchDialog确实不需要了解TestFrame,所有它感兴趣的是JTextComponent ...
  4. 您的“新”示例与现有代码段不一致。您不再将addHighlight的结果分配给last ??
  5. 请勿使用null布局......
  6. 当我最终得到您的示例代码进行编译时,这就是我所呈现的......

    Bad Screen 01

    ......好的,我想,我只是扩大窗口......

    Bad Screen 02

    ......好吧,有一个问题......我没有时间解决。

    避免使用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来优化它(仅重绘已更改的部分)。