---
category: swing
folder: LastLineEditableTextArea
title: JTextAreaの最終行だけ編集可能になるよう設定する
tags: [DocumentFilter, Element, JTextArea, JTextComponent]
author: aterai
pubdate: 2012-12-24T00:48:21+09:00
description: DocumentFilterを使用して最終行のみ編集可能なJTextAreaを作成します。
image: https://lh3.googleusercontent.com/-WoZIsdy2Qd0/UNcd6P73NAI/AAAAAAAABZg/a2O8KLk4hVQ/s800/LastLineEditableTextArea.png
---
* 概要 [#summary]
`DocumentFilter`を使用して最終行のみ編集可能な`JTextArea`を作成します。

#download(https://lh3.googleusercontent.com/-WoZIsdy2Qd0/UNcd6P73NAI/AAAAAAAABZg/a2O8KLk4hVQ/s800/LastLineEditableTextArea.png)

* サンプルコード [#sourcecode]
#code(link){{
class NonEditableLineDocumentFilter extends DocumentFilter {
  public static final String PROMPT = "> ";
  @Override public void insertString(
      DocumentFilter.FilterBypass fb, int offset, String string,
      AttributeSet attr) throws BadLocationException {
    if (string == null) {
      return;
    } else {
      replace(fb, offset, 0, string, attr);
    }
  }

  @Override public void remove(
      DocumentFilter.FilterBypass fb,
      int offset, int length) throws BadLocationException {
    replace(fb, offset, length, "", null);
  }

  @Override public void replace(
      DocumentFilter.FilterBypass fb, int offset, int length,
      String text, AttributeSet attrs) throws BadLocationException {
    Document doc = fb.getDocument();
    Element root = doc.getDefaultRootElement();
    int count = root.getElementCount();
    int index = root.getElementIndex(offset);
    Element cur = root.getElement(index);
    int promptPosition = cur.getStartOffset()+PROMPT.length();
    if (index == count - 1 && offset - promptPosition >= 0) {
      if (text.equals("\n")) {
        String line = doc.getText(promptPosition, offset - promptPosition);
        String[] args = line.split(" ");
        String cmd = args[0];
        if (cmd.isEmpty()) {
          text = "";
        } else {
          text = String.format("%n%s: command not found", cmd);
        }
        text += "\n" + PROMPT;
      }
      fb.replace(offset, length, text, attrs);
    }
  }
}
}}

* 解説 [#explanation]
- `DocumentFilter#replace(...)`をオーバーライド
- `DocumentFilter#replace(...)`メソッドをオーバーライド
- `Document#getDefaultRootElement()`でルートエレメントを取得して`Element#getElementCount()`で全体の行数を取得
- `offset`(文字挿入位置)から`Element#getElementIndex(offset)`メソッドで挿入位置の行番号と`Element`を取得
- `挿入位置の行番号 == 全体の行数 - 1`となる場合のみ`DocumentFilter.FilterBypass#replace(...)`を実行(編集可能)する
-- 上記のサンプルでは、コマンドプロンプト風に最終行の行頭にあるプロンプトは編集不可で改行の入力ごとに最終行の文字列を評価してメッセージを追加表示
-- 上記のサンプルではコマンドプロンプト風に最終行の行頭にあるプロンプトは編集不可で改行の入力ごとに最終行の文字列を評価してメッセージを追加表示

* 参考リンク [#reference]
- [[JTextAreaの一部を編集不可にする>Swing/NonEditableLine]]

* コメント [#comment]
#comment
#comment