2014-11-05 62 views
1

不好意思問這個,因爲還有一些關於同一主題的其他文章,但我沒有設法將這些解決方案應用於我的問題。Java刪除舊的亮點

簡單情況。我有一個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

UPDATE 這裏是一個可運行:(很抱歉的亂碼。)

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

回答

0

感謝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); 
} 

這不是一個最佳的解決方案,因爲你必須重新繪製與每一個變化每熒光筆。但是可以通過增量變化繪製來優化它(只重繪改變的部分)。

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佈局...

當我終於得到了您的示例代碼編譯,這就是我提交了......

Bad Screen 01

...好了,所以想,我只是擴展窗口...

Bad Screen 02

...嗯,有一個問題...我沒有解決的時候。

避免使用null佈局,像素完美的佈局是現代UI設計中的幻想。影響組件的個體大小的因素太多,其中沒有一個可以控制。 Swing旨在與佈局經理一起工作,放棄這些將導致問題和問題的終結,您將花費越來越多的時間來嘗試糾正

有關更多詳細信息,請參閱Why is it frowned upon to use a null layout in SWING? ...

+0

嗯好吧謝謝你的評論。我將嘗試將搜索對話框提取爲可運行的片段。 – Haeri 2014-11-05 22:09:30

+0

好的我更新了OP。 – Haeri 2014-11-05 23:16:28

+0

好的,謝謝你的時間。這是我的第一個Java應用程序,所以我仍然在學習東西。我會按照你所說的更新一切。 PS:我鏈接到一個外部網站,因爲我還沒有想出如何在這裏發佈長代碼片段.. PSS:該死..我用一個空佈局製作了每一個JDialog ..但它看起來不錯我的系統.. :( – Haeri 2014-11-05 23:52:51