2015-05-03 2 views
2

Я пытаюсь создать перезаписывающий Курсор. У меня есть это, только когда я нажимаю более раннюю строку, карет исчезает, а затем, когда я нажимаю «вводить» для новой строки, она появляется снова.Не удается увидеть перезапись курсора при создании новой строки

Что я должен изменить в своем Кодексе, чтобы решить эту проблему?

вот мой Caret Класс:

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

Как я mentione 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. Это должно быть сделано как для методов paint, так и для damage. Также важно отметить, что \n является разделителем строк для системы JTextArea независимо, но другие текстовые компоненты могут иметь разные настройки.

Примечания:

  • При ловле исключения, как минимум вы можете сделать, это распечатать трассировку стека.
  • Я не вижу причины для создания нового объекта Graphics в paint, используя тот, который указан.
  • Используйте @Override, если применимо.
  • Мне просто нужно было сделать чистку (рефакторинг), вы можете взять что-то из этого. Я также изменил конструктор, так как вам не нужно передавать DefaultCaret вашему классу, который расширяет его.
+0

'как-то ширина \ n отрицательна (кто-нибудь, почему?). Это потому, что следующий символ после« \ n »всегда будет на следующей строке. (т. е. getDot() + 1, получит символ из следующей строки). «X» смещение этого символа всегда будет 0. – camickr

+0

@camickr Очень приятно! Это объясняет смелую часть моего первоначального наблюдения «* только в конце ** непустых ** строк, которые не являются последней строкой *». Если строка пуста, ширина будет равна 0, в противном случае это (отрицательная) ширина всех символов в строке. – user1803551

+0

Отличное объяснение. Большое спасибо – user3232446

3

на основе @ user1803551 наблюдений я заметил, что ширина может быть отрицательным, так что я просто изменил свой, если условие "< =" в краске() и повреждения() методы:

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

очень простое решение! Thanx – user3232446

Смежные вопросы