【问题标题】:Java remove old HighlightJava删除旧的Highlight
【发布时间】:2015-01-02 04:02:09
【问题描述】:

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

简单的场景。我有一个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/2563http://hostcode.sourceforge.net/view/2564

【问题讨论】:

    标签: java swing highlight


    【解决方案1】:

    感谢 MadProgrammer,我发现了问题所在:

    对于原始问题“如何移除旧的荧光笔”,答案很简单: 这是我发布的示例代码。

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

    (因为我有两个荧光笔,第一个覆盖了第二个,所以第二个没有出现。这就是我认为我的代码不起作用的原因。)

    对于更新后的问题“如何处理多个荧光笔”,答案也很简单。一个人必须知道的整个事情只有一个问题。荧光笔中的颜料不会被稍后调用的其他荧光笔过度绘制。所以基本上我不得不颠倒荧光笔的调用顺序。 看起来像这样:

    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 来优化这一点(只重绘改变的部分)。

    【讨论】:

      【解决方案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();
                  }
      
              }
      
          }
      }
      

      由于您正在执行此操作,但它不起作用,这表明您的代码存在其他问题,这在您提供的 sn-p 中不明显。考虑提供一个runnable example 来证明您的问题。这将减少混乱并获得更好的响应

      更新...

      1. 不要将您的示例代码链接到外部站点,不是每个人都可以访问外部站点,或者无论如何都不愿意关注链接...
      2. 可运行的示例应该是自包含的,不依赖其他库或资源,例如图标,并且应该包含在单个文件中
      3. 不要不必要地暴露你的UI组件,也就是说,我不认为SearchDialog真的需要了解TestFrame,它感兴趣的只是JTextComponent...
      4. 您的“新”示例和您现有的代码 sn-p 不一致。您不再将addHighlight 的结果分配给last??
      5. 不要使用null 布局...

      当我最终编译你的示例代码时,这就是我看到的......

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

      ...嗯,有个问题...我没时间解决。

      避免使用null 布局,像素完美的布局是现代用户界面设计中的一种错觉。影响组件单个尺寸的因素太多,您无法控制。 Swing 旨在与核心的布局管理器一起工作,丢弃这些将导致无穷无尽的问题和问题,您将花费越来越多的时间来尝试纠正

      查看Why is it frowned upon to use a null layout in SWING?了解更多详情...

      【讨论】:

      • 嗯好的,谢谢你的评论。我将尝试将搜索对话框提取到可运行的 sn-p 中。
      • 好的,谢谢您的宝贵时间。这是我的第一个 java 应用程序,所以我还在学习。我会按照你说的更新一切。 PS:我链接到一个外部站点,因为我还没有弄清楚如何在这里发布长代码 sn-ps.. PSS:该死.. 我用空布局制作了每一个 JDialog.. 但它看起来很不错我的系统.. :(
      • 我使用不同的字体和字体点然后正常 - 主要是因为我正在使用的系统以前的开发人员搞砸了布局,所以我使用不同的字体/大小来解决这些问题,这就像我日常工作的 90%...现在您知道为什么我不喜欢 null 布局或使用 setPreferredSize 的人... ;)
      • 所以我没有修复示例代码,而是修改了原始代码并发现:我发布的原始代码示例完全有效。它没有出现在我身上,因为我有第二个荧光笔,由于某种原因,它不允许我的红色荧光笔覆盖这些亮点。所以我不得不把问题改成:How to manage multiple Highlighter access to the same text sn-p.
      • 最好的,新的,问题;)
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-01-24
      • 1970-01-01
      • 1970-01-01
      • 2019-05-13
      • 2018-10-18
      相关资源
      最近更新 更多