2015-05-03 86 views
2

我試圖創建一個覆蓋光標。除了當我點擊較早的一行時插入符號消失時,我已經得到了它,然後當我點擊「輸入」換行時,它再次出現。當我創建新行時,無法看到Overwrinting光標

我應該在我的代碼中更改哪些內容來解決此問題?

這裏是我的插入級:

public class Mycaret extends DefaultCaret { 

    protected static final int MIN_WIDTH = 8; 

    protected DefaultCaret dc = null; 

    JTextComponent com = null; 

    public Mycaret(int rate, DefaultCaret dc) { 

     this.dc = dc; 
     super.setBlinkRate(rate); 
    } 

    protected synchronized void damage(Rectangle r) { 

     if (r != null) { 

      try { 

       JTextComponent comp = getComponent(); 
       TextUI mapper = comp.getUI(); 
       char dotChar = 0; 
       if(comp.getText().length()>0){ 
       dotChar = comp.getText().charAt(comp.getText().length()-1); 
       } 
       this.com = comp; 

       Rectangle r2 = mapper.modelToView(comp, getDot() + 1); 

       int width = r2.x - r.x; 

       if (width == 0) { 

        width = MIN_WIDTH; 


       } 

       comp.repaint(r.x, r.y, width, r.height); 

       this.x = r.x; 
       this.y = r.y; 
       this.width = width; 
       this.height = r.height; 

      } 

      catch (BadLocationException e) { 

      } 
     } 

    } 

    public void paint(Graphics g) { 

     char dotChar; 

     if (isVisible()) { 

      try { 

       JTextComponent comp = getComponent(); 
       TextUI mapper = comp.getUI(); 

       Rectangle r1 = mapper.modelToView(comp, getDot()); 
       Rectangle r2 = mapper.modelToView(comp, getDot() + 1); 

       g = g.create(); 
       g.setColor(comp.getForeground()); 
       g.setXORMode(comp.getBackground()); 

       int width = r2.x - r1.x; 

       dotChar = comp.getText(getDot(), 1).charAt(0); 

       if (width == 0 ) { 
        width = MIN_WIDTH; 

       } 



       g.fillRect(r1.x, r1.y, width, r1.height); 
       g.dispose(); 

      } catch (BadLocationException e) { 

      } 
     } 

    } 
} 

這是一個示例:

public class MyFrameSample extends JFrame { 

    DefaultCaret caret=null; 

    public MyFrameSample() { 

     JTextArea text = new JTextArea(10,20); 
     caret = new DefaultCaret(); 

     text.setCaret(new Mycaret(500, caret)); 
     add(text); 

     pack(); 
     setVisible(true); 
    } 

    public static void main(String[] args) { 

     new MyFrameSample(); 
    } 
} 
+0

我編輯了我的問題 – user3232446

+0

是的,這應該是我的問題:) – user3232446

+1

我想我在這方面有領先。我建議這是因爲'modelToView(comp,getDot()+ 1)'中的陷阱而發生的。請注意,胡蘿蔔只會在非空行的末尾停止渲染*,而不是最後一行*。這些位置正好在'\ n'坐在文檔中的位置。由於胡蘿蔔需要'getDot()'和'getDot()+ 1'之間的寬度,並且'\ n'不可見,所以你會看到一個看不見的胡蘿蔔。 – user1803551

回答

2

正如我提到的d在評論中,問題來自換行符(\n)。當插入符號被放在非空行的\n之前時,它不會出現,因爲它會嘗試取\n的寬度。因此,我添加了一張支票,看看\n是否處於與插入符號相同的位置。

中秋節寫編輯: @camickr通過尋找莫名其妙\n寬度爲負想出一個更好的辦法(任何人,爲什麼看評論?)。

public class Mycaret extends DefaultCaret { 

    protected static final int MIN_WIDTH = 8; 

    public Mycaret(int rate) { 

     super.setBlinkRate(rate); 
    } 

    protected boolean isBeforeNewLine() throws BadLocationException { 

     PlainDocument doc = (PlainDocument) getComponent().getDocument(); 
     if (doc.getText(getDot(), 1).equals("\n")) 
      return true; 
     return false; 
    } 

    @Override 
    protected synchronized void damage(Rectangle r) { 

     if (r != null) { 
      try { 
       JTextComponent comp = getComponent(); 

       Rectangle r2 = comp.getUI().modelToView(comp, getDot() + 1); 
       int width = r2.x - r.x; 
       if (width == 0 || isBeforeNewLine()) { 
        width = MIN_WIDTH; 
       } 
       comp.repaint(r.x, r.y, width, r.height); 

       this.x = r.x; 
       this.y = r.y; 
       this.width = width; 
       this.height = r.height; 
      } catch (BadLocationException e) { 
       e.printStackTrace(); 
      } 
     } 
    } 

    @Override 
    public void paint(Graphics g) { 

     if (isVisible()) { 
      try { 
       JTextComponent comp = getComponent(); 

       g.setColor(comp.getForeground()); 
       g.setXORMode(comp.getBackground()); 

       Rectangle r1 = comp.getUI().modelToView(comp, getDot()); 
       Rectangle r2 = comp.getUI().modelToView(comp, getDot() + 1); 
       int width = r2.x - r1.x; 
       if (width == 0 || isBeforeNewLine()) { 
        width = MIN_WIDTH; 
       } 
       g.fillRect(r1.x, r1.y, width, r1.height); 
      } catch (BadLocationException e) { 
       e.printStackTrace(); 
      } 
     } 
    } 
} 

說明:

isBeforeNewLine方法在獲取從文檔中插入符號的位置的文本。對於JTextArea這是一個PlainDocument。如果它是\n那麼寬度設置爲MIN_WIDTH。必須對paintdamage方法進行此操作。同樣重要的是要注意,\n是系統獨立的JTextArea的行分隔符,但其他文本組件的設置可能不同。

注:

  • 當捕獲異常,你至少可以做的是打印堆棧跟蹤。
  • 我沒有看到在paint中創建新的Graphics對象的原因,請使用給定的對象。
  • 適用時使用@Override
  • 我只需要做一些清理(重構),你可能想從中獲得一些東西。我也更改了構造函數,因爲您不需要將DefaultCaret傳遞給擴展它的類。
+0

'不知怎的,\ n的寬度是負數(任何人,爲什麼?)。「這是因爲」\ n「後面的下一個字符總是在下一行。 (即getDot()+ 1)將從下一行獲取字符)。該字符的「x」偏移將始終爲0. – camickr

+0

@camickr非常好!這解釋了我最初觀察中的大膽部分「*僅在**非空**行的末尾,這不是最後一行*」。如果該行爲空,則寬度將爲0,否則爲該行中所有字符的(負)寬度。 – user1803551

+0

很好的解釋。非常感謝 – user3232446

3

基於@ user1803551的觀察,我注意到,寬度可能是負的,所以我只是改變了你,如果條件「< =」在paint()和damage()方法中:

if (width <= 0 ) 
{ 
    width = MIN_WIDTH; 
} 
+0

一個非常簡單的解決方案! Thanx – user3232446

相關問題