テキスト関連

テキスト編集用のGUIコンポーネントは、JTextFieldクラス、JTextAreaクラス、 JEditorPaneクラス、JTextPaneクラスと用意されます。
これらはどのように使い分ければよいのでしょうか?
おおざっぱに説明すると、 1行編集用にJTextFieldクラス、 複数の行を編集できるJTextAreaクラス、 さまざまな種類のコンテンツを編集するためのJEditorPaneクラス、 イメージなどの組み込み可能なJTextPaneクラスとなります。

詳細は次のリンクで調べましょう。

java.lang.Object
 └java.awt.Component
  └java.awt.Container
   └javax.swing.JComponent
    └javax.swing.text.JTextComponent
     └javax.swing.JTextField

java.lang.Object
 └java.awt.Component
  └java.awt.Container
   └javax.swing.JComponent
    └javax.swing.text.JTextComponent
     └javax.swing.JTextArea

java.lang.Object
 └java.awt.Component
  └java.awt.Container
   └javax.swing.JComponent
    └javax.swing.text.JTextComponent
     └javax.swing.JEditorPane
      └javax.swing.JTextPane

これらテキストの編集クラスは、 JTextComponentクラスを継承しています。
このクラスは、オペレータ編集操作のユーザインタフェースを実装しています。
しかし、プログラムでテキストコンポーネントの内容を 操作する目的のクラスではありません。
テキスト操作メソッドを持つ javax.swing.text.Documentインターフェイス実装クラスの オブジェクトが、操作対象のテキストコンポーネントの内容を持っていて、 こちらがプログラム操作の役割に使うクラスです。このDocument継承オブジェクトは、 JTextComponentのgetDocumentメソッドで得ることができます。

Document document=JTextComponentオブジェクト.getDocument()

こうして、取得したdocumentオブジェクトで挿入( insertString)や 指定範囲の削除(remove)が可能です。
以下では、JTextField、 JTextArea、 JEditorPane、 JTextPaneのインスタンスを順番に並べて、それぞれに対してボタンで 挿入や削除が実験できます。
挿入する場合には、属性指定で行っていますが、 documentで管理されるインスタンスが、PlainDocumentでは指定に意味がありません。
documentで管理されるインスタンスが、DefaultStyledDocumentであれば、属性指定が有効になります。
なお、Highlighterによる背景ペイントは、全てに対して有効なことが分かります。

以下にこのソースを示します。

package testtext;//JFrame作品
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.text.*; //インタフェース Document

class MainPanelTestDocument extends JPanel implements  ActionListener
{
	JTextField textField;
	JTextArea textArea;
	JEditorPane editorPane;
	JTextPane textPane;
	
	JButton btn挿入 = new JButton("先頭位置へ挿入");
	JButton btn削除 = new JButton("1から4まで削除");
	JButton btnハイライト = new JButton("1から4までハイライト");

	String data = "abc\nあいうえお\nかき";
	SimpleAttributeSet attribute = new SimpleAttributeSet();

	MainPanelTestDocument() {// コンストラクタ
		this.setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS));
		this.add(Box.createHorizontalGlue());  //横方向の伸縮スペース


		//テキストフィールドの1行を生成して追加
		textField = new JTextField(data);
		add(textField);

		//テキストエリアの複数行を生成して追加
		textArea = new JTextArea(data);
		add(textArea);

		//エディタパインを生成して追加し、文字列を設定
		editorPane = new JEditorPane("text/plain", "");
		add(editorPane);
		editorPane.setText(data);//"text/rtf"で生成時は、設定できない。(plainで可能になる。)

		//エディタパインを生成して追加し、文字列を設定
		textPane = new JTextPane();
		textPane.setText("abc\nあいうえお\nかき");
		add(textPane);

		//ボタン配置とリスナー設定
		add(btn挿入);
		add(btn削除);
		add(btnハイライト);
		btn挿入.setAlignmentX(JComponent.CENTER_ALIGNMENT);
		btn削除.setAlignmentX(JComponent.CENTER_ALIGNMENT);
		btnハイライト.setAlignmentX(JComponent.CENTER_ALIGNMENT);
		btn挿入.addActionListener(this);
		btn削除.addActionListener(this);
		btnハイライト.addActionListener(this);
		
		this.setPreferredSize(new Dimension(200, 300));
	}
	
	public void actionPerformed(ActionEvent e){
		Object obj = e.getSource();
		if(obj == btn挿入){
			//属性情報を作成 属性情報の文字色に赤、背景を黄色に設定
			attribute.addAttribute(StyleConstants.Foreground, Color.RED);
			attribute.addAttribute(StyleConstants.Background, Color.YELLOW);

			try{
				//ドキュメントにその属性情報つきの文字列を挿入
				Document document = textField.getDocument();
				document.insertString(0, "さしすせそ\n", attribute);
				System.out.println(document.getClass().getName());//javax.swing.text.PlainDocumentの表示

				document = textArea.getDocument();
				document.insertString(0, "さしすせそ\n", attribute);//attributeの指定をしない場合はnullの指定が可能
				System.out.println(document.getClass().getName());//javax.swing.text.PlainDocumentの表示

				document = editorPane.getDocument();
				document.insertString(0, "さしすせそ\n", attribute);
				System.out.println(document.getClass().getName());//javax.swing.text.PlainDocumentの表示

				document = textPane.getDocument();
				document.insertString(0, "さしすせそ\n", attribute);
				System.out.println(document.getClass().getName());//javax.swing.text.DefaultStyledDocumentの表示
			}
			catch (Exception err){
				err.printStackTrace();
			}
		} else if (obj == btn削除){
			try	{
				//ドキュメントでの指定範囲の文字列を削除
				Document document = textField.getDocument();
				document.remove(1, 4);

				document = textArea.getDocument();
				document.remove(1, 4);

				document = editorPane.getDocument();
				document.remove(1, 4);

				document = textPane.getDocument();
				document.remove(1, 4);
			}
			catch (Exception err){
				err.printStackTrace();
			}
		} else if (obj == btnハイライト){
			try	{
				//部分的にハイライトのペイントを施す
				addHighlight(textField, 1, 4, Color.CYAN);
				addHighlight(textArea, 1, 4, Color.CYAN);
				addHighlight(editorPane, 1, 4, Color.CYAN);
				addHighlight(textPane, 1, 4, Color.CYAN);
			}
			catch (Exception err){
				err.printStackTrace();
			}
		}
	}

	//指定の位置のハイライトを追加する。
	public static void addHighlight(JTextComponent textComponent, int iStart, int iEnd, Color color){
		javax.swing.text.DefaultHighlighter.DefaultHighlightPainter highlightPainter =
			new javax.swing.text.DefaultHighlighter.DefaultHighlightPainter(color);
		Highlighter highlighter = textComponent.getHighlighter();

		try{
			highlighter.addHighlight(iStart, iEnd, highlightPainter);
		}
		catch (BadLocationException e){
		}
	}
}

class TestDocumentFrame extends JFrame {
	public TestDocumentFrame(){
		this.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
		this.setContentPane(new MainPanelTestDocument());
	}

	public static void main(String []agrs){
		JFrame frame = new TestDocumentFrame();
		frame.pack();
		frame.setVisible(true);
	}
}