#navi(../)
*JTextAreaのキャレットを上書きモード対応にする [#bce20037]
>編集者:[[Terai Atsuhiro>terai]]~
作成日:2006-01-16~
更新日:&lastmod;

#contents

**概要 [#l6341a56]
JTextAreaにキャレット上の文字を上書きする上書きモードを追加します。

[[Java Forums - JTextPane edit mode (insert or overwrite)???>http://forum.java.sun.com/thread.jspa?forumID=57&threadID=667407]]のソースコードを変更して全角文字対応にしています。

#screenshot

**サンプルコード [#hf545cfe]
 // Paint a horizontal line the width of a column and 1 pixel high
 class OvertypeCaret extends DefaultCaret {
   //The overtype caret will simply be a horizontal line
   //one pixel high (once we determine where to paint it)
   public void paint(Graphics g) {
     if(isVisible()) {
       try{
         JTextComponent component = getComponent();
         TextUI mapper = component.getUI();
         Rectangle r = mapper.modelToView(component, getDot());
         g.setColor(component.getCaretColor());
         int width = g.getFontMetrics().charWidth('w');
         //全角などに対応
         if(isOvertypeMode()) {
           int pos = getCaretPosition();
           if(pos<getDocument().getLength()) {
             if(getSelectedText()!=null) {
               width = 0;
             }else{
               String str = getText(pos, 1);
               width = g.getFontMetrics().stringWidth(str);
             }
           }
         } //ここまで追加
         int y = r.y + r.height - 2;
         g.drawLine(r.x, y, r.x + width - 2, y);
       }catch(BadLocationException e) {}
     }
   }
   // Damage must be overridden whenever the paint method is overridden
   // (The damaged area is the area the caret is painted in. We must
   // consider the area for the default caret and this caret)
   protected synchronized void damage(Rectangle r) {
     if(r != null) {
       JTextComponent c = getComponent();
       x = r.x;
       y = r.y;
       //width = c.getFontMetrics(c.getFont()).charWidth('w');
       //全角対応
       width = c.getFontMetrics(c.getFont()).charWidth('あ');
       height = r.height;
       repaint();
     }
   }
 }

-&jnlp;
-&jar;
-&zip;

**解説 [#o73b8338]
上記のサンプルでは、上書きモード用のキャレットを作成して、Insertキーで切り替えるようになっています。

上書きモード自体の動作は、JTextArea#replaceSelectionメソッドをオーバーライドすることで行われています。上書きモードの場合、次の文字までを選択して置き換える処理がここで追加されています。

**参考リンク [#c7f33248]
-[[Java Forums - JTextPane edit mode (insert or overwrite)???>http://forum.java.sun.com/thread.jspa?forumID=57&threadID=667407]]

**コメント [#n3e0ddb6]
- 改行の処理がまだいい加減です。 -- [[terai]] &new{2006-01-16 (月) 15:56:38};
- テキストを選択状態にしてInsertキーを押すと、反転されたままになるようなので修正。 -- [[terai]] &new{2006-01-16 (月) 18:45:02};
- IME起動時、「あ」を入力し、変換キー(or spaceキー)を押すたびに減っていきます。日本語対応のソースを心待ちにしています。 -- [[初心者]] &new{2006-03-24 (金) 10:40:01};
- バグですね。報告ありがとうございます。減らないように修正はしたのですが、置換は以下のように適当です。 -- [[terai]] &new{2006-03-24 (金) 16:26:25};
 aaaabbbb   //元のテキストの先頭でああと入力、変換して確定すると
 嗚呼bbbb   //こうならずに
 嗚呼aabbbb //こうなってしまう(まじめにやれば、なんとかなりそうだが)

#comment