2011-03-23 85 views
8

我試圖超過2天實現對文本編輯器窗口中的具體要求......可惜沒有成功,到目前爲止:(突出顯示當前行中的JTextPane

的目標是獲得一個文本編輯器窗口這將突出顯示當前行,就像其他文本編輯器一樣。對於當前行,我指的是當前光標/光標所在的行。

我已經找到了兩種不同的方法,但不幸的是我無法採用它們他們按預期工作

第一種方法是覆蓋DefaultHighlighterhttp://snippets.dzone.com/posts/show/6688)。 在第二種方法中,HighlighterPainter將被覆蓋,而不是(http://www.jroller.com/santhosh/date/20050622)。

現在我正試圖在我的項目中採用第一種方法,但正如我所說的那樣,它不能按需要工作。

在本文末尾,我發佈了一個小示例應用程序,演示了這個問題。

  • 如果我啓動該程序,插入符號將被放置在第一行的開頭。但是,該行不突出顯示。
  • 現在我輸入一些字符。那些字符將突出顯示,但只有那些字符不是完整的行
  • 我按Enter鍵移動到下一行。第一行不再突出顯示什麼是正確的。第二行也沒有突出顯示,什麼是不正確的。再次,當我輸入一些字符時,這些字符會被加亮,但不是完整的字符。
  • 當我現在將插入符號移回第一行時,無論是通過向上鍵還是鼠標單擊,完整的第一行都將突出顯示,而不僅僅是現有的字符。這是我從一開始就想要的行爲。

我希望任何人都可以告訴我在這裏做錯了什麼......或者解釋爲什麼根本無法解決這個問題。任何替代解決方案我如何能夠實現突出顯示的行也非常感謝!

感謝很多提前 乾杯 Preachie

import java.awt.Color; 
import java.awt.Dimension; 
import java.awt.Graphics; 
import java.awt.Insets; 
import java.awt.Rectangle; 

import javax.swing.JFrame; 
import javax.swing.JTextPane; 
import javax.swing.event.CaretEvent; 
import javax.swing.event.CaretListener; 
import javax.swing.text.DefaultHighlighter; 
import javax.swing.text.Highlighter; 
import javax.swing.text.JTextComponent; 

public class HighlightProblem extends JFrame { 
    private static final long serialVersionUID = 1L; 
    private final JTextPane textPane; 
    private final Highlighter.HighlightPainter cyanPainter; 

    public HighlightProblem() { 
     cyanPainter = new DefaultHighlighter.DefaultHighlightPainter(Color.CYAN); 

     textPane = new JTextPane(); 
     textPane.setPreferredSize(new Dimension(500, 300)); 
     textPane.setHighlighter(new LineHighlighter()); 
     textPane.addCaretListener(new CaretListener() { 
      @Override 
      public void caretUpdate(CaretEvent e) { 
       setHighlight(e); 
      } 
     }); 
     getContentPane().add(textPane); 
     setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     pack(); 
     setVisible(true); 
    } 

    public static void main(String[] args) { 
     new HighlightProblem(); 
    } 

    public void setHighlight(CaretEvent e) { 
     textPane.getHighlighter().removeAllHighlights(); 
     int currentLine = getLineFromOffset(textPane, e.getDot()); 
     int startPos = getLineStartOffsetForLine(textPane, currentLine); 
     int endOffset = getLineEndOffsetForLine(textPane, currentLine); 

     try { 
      textPane.getHighlighter().addHighlight(startPos, endOffset, cyanPainter);   
     } catch (Exception ex) { 
      ex.printStackTrace(); 
     } 
     textPane.repaint(); 
    } 

    public int getLineFromOffset(JTextComponent component, int offset) { 
     return component.getDocument().getDefaultRootElement().getElementIndex(offset); 
    } 

    public int getLineStartOffsetForLine(JTextComponent component, int line) { 
     return component.getDocument().getDefaultRootElement().getElement(line).getStartOffset(); 
    } 

    public int getLineEndOffsetForLine(JTextComponent component, int line) { 
     return component.getDocument().getDefaultRootElement().getElement(line).getEndOffset(); 
    } 

    public class LineHighlighter extends DefaultHighlighter { 
     private JTextComponent component; 

     @Override 
     public final void install(final JTextComponent c) { 
      super.install(c); 
      this.component = c; 
     } 

     @Override 
     public final void deinstall(final JTextComponent c) { 
      super.deinstall(c); 
      this.component = null; 
     } 

     @Override 
     public final void paint(final Graphics g) { 
      final Highlighter.Highlight[] highlights = getHighlights(); 
      final int len = highlights.length; 
      for (int i = 0; i < len; i++) { 
       Highlighter.Highlight info = highlights[i]; 
       if (info.getClass().getName().indexOf("LayeredHighlightInfo") > -1) { 
        // Avoid allocing unless we need it. 
        final Rectangle a = this.component.getBounds(); 
        final Insets insets = this.component.getInsets(); 
        a.x = insets.left; 
        a.y = insets.top; 
        // a.width -= insets.left + insets.right + 100; 
        a.height -= insets.top + insets.bottom; 
        final Highlighter.HighlightPainter p = info.getPainter(); 
        p.paint(g, info.getStartOffset(), info.getEndOffset(), a, this.component); 
       } 
      } 
     } 

     @Override 
     public void removeAllHighlights() { 
      textPane.repaint(0, 0, textPane.getWidth(), textPane.getHeight()); 
      super.removeAllHighlights(); 
     } 
    } 
} 

回答

3

http://tips4java.wordpress.com/2008/10/29/line-painter/

我認爲這是你在找什麼。我把那LinePainter類,並在拷貝構造函數爲主要方法,拿出你的高亮部分,並增加了new LinePainter(textPane);就像一個魅力

+0

非常感謝......它看起來真的很喜歡它的工作就像一個魅力。 – Preachie 2011-03-23 14:35:08

+0

不客氣。 :) – spedsal 2011-03-23 14:42:52

1

我認爲這可能是難以用熒光筆實現 - 我不認爲這是他們是爲什麼而設計的。您可能需要使用自定義繪畫代碼:

import java.awt.Color; 
import java.awt.Graphics; 
import java.awt.Rectangle; 

import javax.swing.JFrame; 
import javax.swing.JTextPane; 
import javax.swing.text.BadLocationException; 

public class HighlightLineTest { 
    private static class HighlightLineTextPane extends JTextPane { 
     public HighlightLineTextPane() { 
      // Has to be marked as transparent so the background is not replaced by 
      // super.paintComponent(g); 
      setOpaque(false); 
     } 

     @Override 
     protected void paintComponent(Graphics g) { 
      g.setColor(getBackground()); 
      g.fillRect(0, 0, getWidth(), getHeight()); 
      try { 
       Rectangle rect = modelToView(getCaretPosition()); 
       if (rect != null) { 
        g.setColor(Color.CYAN); 
        g.fillRect(0, rect.y, getWidth(), rect.height); 
       } 
      } catch (BadLocationException e) { 
      } 
      super.paintComponent(g); 
     } 

     @Override 
     public void repaint(long tm, int x, int y, int width, int height) { 
      // This forces repaints to repaint the entire TextPane. 
      super.repaint(tm, 0, 0, getWidth(), getHeight()); 
     } 
    } 

    public static void main(String[] args) { 
     JFrame frame = new JFrame("Highlight test"); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.add(new HighlightLineTextPane()); 
     frame.setBounds(100, 100, 300, 400); 
     frame.setVisible(true); 
    } 
} 
2

下面是從當前行中提取文本的代碼。 您可以使用相同的邏輯來獲得所需的指標和突出顯示文本

private String getCurrentEditLine() { 
     int readBackChars = 100; 
     int caretPosition = scriptEditor.getCaretPosition(); 

     if (caretPosition == 0) { 
      return null; 
     } 

     StyledDocument doc = scriptEditor.getStyledDocument(); 

     int offset = caretPosition <= readBackChars ? 0 : caretPosition 
       - readBackChars; 

     String text = null; 
     try { 
      text = doc.getText(offset, caretPosition); 
     } catch (BadLocationException e) { 
     } 

     if (text != null) { 
      int idx = text.lastIndexOf("\n"); 
      if(idx != -1) { 
       return text.substring(idx); 
      }else { 
       return text; 
      } 
     } 

     return null; 
    } 
相關問題