AttributeSetインターフェース

広告

ここでは、様々なスタイルを実際にどのように反映させるかについて見ていきます。

既存の文書に対してスタイルを変更する場合は、どの部分の文書のスタイルを変えるのかの範囲指定と、その範囲をどのようなスタイルにするかの指定が必要となります。

取り合えず簡単な例から見てください。下記は指定の範囲だけをBOLDにするだけの簡単なサンプルです。

import javax.swing.*;
import javax.swing.text.*;

public class TextPaneTest extends JFrame{

  public static void main(String[] args){
    TextPaneTest test = new TextPaneTest();

    test.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    test.setVisible(true);
  }

  TextPaneTest(){
    setTitle("TextPaneTest Test");
    setBounds( 10, 10, 300, 200);

    JTextPane textPane = new JTextPane();
    JScrollPane scroll = new JScrollPane(textPane, 
      JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, 
      JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);

    getContentPane().add(scroll);

    StyleContext sc = new StyleContext();
    DefaultStyledDocument doc = new DefaultStyledDocument(sc);

    textPane.setDocument(doc);

    /* 初期文書の読み込み */
    initDocument(doc, sc);

    /* スタイルの変更 */
    changeStyle(doc);
  }

  protected void initDocument(DefaultStyledDocument doc, StyleContext sc){
    StringBuffer sb = new StringBuffer();
    sb.append("スタイル付きのテキストサンプルです。¥n");
    sb.append("スタイルを変えて表示しています。");

    try{
      /* 文書を挿入する */
      doc.insertString(0, new String(sb), 
        sc.getStyle(StyleContext.DEFAULT_STYLE));
    }catch (BadLocationException ble){
      System.err.println("初期文書の読み込みに失敗しました。");
    }
  }

  protected void changeStyle(DefaultStyledDocument doc){
    MutableAttributeSet attr = new SimpleAttributeSet();
    StyleConstants.setBold(attr, true);

    /* 4文字目から8文字分だけスタイルを変更する */
    doc.setCharacterAttributes(4, 8, attr, false);
  }
}

実行結果は下記のようになります。

上記のサンプルでは2つのことをしています。まずDefaultStyledDocumentクラスのinsertStringメソッド(実際にはAbstractDocumentで用意されています)を使って用意した文字列をDocumentに挿入しています。

次にDefaultStyledDocumentクラスのsetCharacterAttributesメソッドを使って指定した範囲のスタイルを変更しています。

取り合えずこの2つのメソッドを見てみましょう。

ドキュメントに内容を挿入します。内容の挿入によって、実際の変更が起きるまでは書き込みロック
が保持されます。そのあとで、書き込みロックをグラブしているスレッド上のオブザーバに通知が行
われます。

パラメータ:
  offs - 開始オフセット >= 0
  str - 挿入する文字列。null や空の文字列の場合は何もしない
  a - 挿入されたコンテンツの属性 
例外: 
  BadLocationException - 指定された挿入の位置が、ドキュメント内の有効な位置ではない場合

指定した位置(offs)に指定した文字(str)を指定したスタイル(a)で文書を挿入します。先ほどの例では、まだ何も文書が無いので、文書の先頭に文書を挿入しています。スタイルで使っているAttributeSet(インターフェース)については後で確認します。

またこのメソッドは例外としてBadLocationExceptionを投げますので、その処理をしておきます。

ドキュメントの一部に属性を設定します。この処理は変更の実行中に書き込みロックを保持し、変更
が適切に完了すると DocumentEvent がリスナーに送られます。

パラメータ:
  offset - ドキュメントのオフセット >= 0
  length - 長さ >= 0
  s - 属性
  replace - 新しい属性の設定前に従来の属性を置換する必要がある場合は true

指定した位置(offset)から長さ(length)分だけ指定したスタイル(s)に設定いたします。replaceにてtrueを指定すると、もともとも設定してあったスタイルを全て破棄して新しいスタイルを設定します。falseを指定した場合は、今までの設定を残したまま、変更したい部分だけを置き換えます(例えば、フォントの種類やサイズは変更せずに、BOLDだけにしたい場合などはfalseにします)。

insertString及びsetCharacterAttributesでもスタイルの指定としてAttributeSetインターフェースが使われています。これはどんなものなのかを細かく調べてみましょう。

AttributeSetインターフェースとは

スタイル情報を保存するためのものとして、AttributeSetインターフェース、そのサブクラスであるMutableAttributeSetインターフェース、さらにそのサブクラスであるStyleインターフェースがあります。

実のところMutableAttributeSetインターフェースとStyleインターフェースをどう使い分けるのかよく分かっていないのですが、実装クラスとして用意されているのがMutableAttributeSetインターフェースを実装したSimpleAttributeSetクラスだけなので、取り合えずこのクラスを使って調べてみます。

SimpleAttributeSetクラスのクラス図は下記のようになります。

public class SimpleAttributeSet
extends Object implements MutableAttributeSet, Serializable, Cloneable
java.lang.Object
 L javax.swing.text.SimpleAttributeSet

コンストラクタとしては下記の2つが用意されています。

コンストラクタの概要
SimpleAttributeSet()
新しい属性セットを作成します。
SimpleAttributeSet(AttributeSet source)
指定された属性セットに基づいて新しい属性セットを作成します。

SimpleAttributeSetクラスのオブジェクトは、ハッシュテーブルをベースに作られていて、"名前"と"値"のペアを必要なだけ持つようになっています。2番目のコンストラクタは、既にあるAttributeSetのデータを元に作成する場合となります。新規に作る場合は、1番目のコンストラクタを利用します。

作成したスタイル情報を保持する箱に値をセットするのは、addAttributeメソッドを使います。

リストに属性を追加します。

パラメータ:
  name - 属性名
  value - 属性値

このメソッドでは、パラメータで指定した名前と値のペアを登録します。例えばBOLDをtrueにするには

SimpleAttributeSet sa = new SimpleAttributeSet();
sa.addAttribute(StyleConstants.FontConstants.Bold, true);

ただこの記述方法だと、"名前"のところに何を書くのか、それに対応した"値"のところにどんな種類の値を設定すればいいのかが分かりにくいため、StyleConstantsクラスという便利なクラスが用意されていますので、通常はこちらを使えばいいかと思います。

次はStyleConstantsクラスを見てみましょう。

StyleConstantsクラスとは

まず、StyleConstantsクラスのクラス図を見てみます。

public class StyleConstants
extends Object
java.lang.Object
 L javax.swing.text.StyleConstants

このクラスではコンストラクタでオブジェクトを作成するのではなく、下記のような感じで使います。

SimpleAttributeSet sa = new SimpleAttributeSet();
StyleConstants.setBold(sa, true);

上記の場合は、まず箱を作り、その箱に対してBOLDの情報を登録しています。"名前"と"値"のペアで登録する代わりに、名前毎のメソッドが用意されているので、直感的に理解しやすいのではと思います。

StyleConstantsクラスでは色々なメソッドが用意されているのですが、いくつか見てみましょう。

ボールド属性を設定します。

パラメータ:
  a - 属性セット
  b - 属性を設定するための true/false を指定する

このメソッドではBOLDにするかどうかをtrue/falseで指定します。

イタリック属性を設定します。

パラメータ:
  a - 属性セット
  b - 属性を設定するための true/false を指定する

このメソッドではITALICにするかどうかをtrue/falseで指定します。

フォアグラウンドカラーを設定します。

パラメータ:
  a - 属性セット
  fg - 色

このメソッドでは文字の表示色をFontクラスのオブジェクトで指定します。

バックグラウンドカラーを設定します。

パラメータ:
  a - 属性セット
  fg - 色

このメソッドでは文字の背景色をFontクラスのオブジェクトで指定します。

フォントの属性を設定します。 

パラメータ:
  a - 属性セット
  fam - フォント

このメソッドでは文字のフォント名をフォントのファミリー名で指定します。

フォントサイズを設定します。

パラメータ:
  a - 属性セット
  s - フォントサイズ

このメソッドでは文字のフォントサイズを数字で指定します。

下線属性を設定します。

パラメータ:
  a - 属性セット
  b - 属性を設定するための true/false を指定する

このメソッドでは文字にアンダーラインを引くかどうかをtrue/falseで指定します。

取り消し線属性を設定します。

パラメータ:
  a - 属性セット
  b - 属性を設定するための true/false を指定する

このメソッドでは文字に取り消し線を引くかどうかをtrue/falseで指定します。

他にも色々あるのですが、取り合えずこんなところを試してみましょう。

import javax.swing.*;
import javax.swing.text.*;
import java.awt.Color;

public class TextPaneTest extends JFrame{

  public static void main(String[] args){
    TextPaneTest test = new TextPaneTest();

    test.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    test.setVisible(true);
  }

  TextPaneTest(){
    setTitle("TextPaneTest Test");
    setBounds( 10, 10, 300, 200);

    JTextPane textPane = new JTextPane();
    JScrollPane scroll = new JScrollPane(textPane, 
      JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, 
      JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);

    getContentPane().add(scroll);

    StyleContext sc = new StyleContext();
    DefaultStyledDocument doc = new DefaultStyledDocument(sc);

    textPane.setDocument(doc);

    /* 初期文書の読み込み */
    initDocument(doc, sc);

    /* スタイルの変更 */
    changeStyle(doc);
  }

  protected void initDocument(DefaultStyledDocument doc, StyleContext sc){
    StringBuffer sb = new StringBuffer();
    sb.append("スタイル付きのテキストサンプルです。¥n");
    sb.append("スタイルを変えて表示しています。");

    try{
      /* 文書を挿入する */
      doc.insertString(0, new String(sb), 
        sc.getStyle(StyleContext.DEFAULT_STYLE));
    }catch (BadLocationException ble){
      System.err.println("初期文書の読み込みに失敗しました。");
    }
  }

  protected void changeStyle(DefaultStyledDocument doc){
    MutableAttributeSet attr1 = new SimpleAttributeSet();
    StyleConstants.setBold(attr1, true);
    /* 4文字目から8文字分だけBOLDへ */
    doc.setCharacterAttributes(4, 8, attr1, false);

    MutableAttributeSet attr2 = new SimpleAttributeSet();
    StyleConstants.setItalic(attr2, true);
    /* 6文字目から4文字分だけITALICへ */
    doc.setCharacterAttributes(6, 4, attr2, false);

    MutableAttributeSet attr3 = new SimpleAttributeSet();
    StyleConstants.setForeground(attr3, Color.red);
    StyleConstants.setBackground(attr3, Color.black);
    /* 2文字目から4文字分だけ色を変更へ */
    doc.setCharacterAttributes(2, 4, attr3, false);

    MutableAttributeSet attr4 = new SimpleAttributeSet();
    StyleConstants.setFontFamily(attr4, "HGP行書体");
    StyleConstants.setFontSize(attr4, 24);
    /* 20文字目から6文字分だけフォントとサイズを変更へ */
    doc.setCharacterAttributes(20, 6, attr4, false);

    MutableAttributeSet attr5 = new SimpleAttributeSet();
    StyleConstants.setUnderline(attr5, true);
    /* 8文字目から5文字分だけアンダーラインを引く */
    doc.setCharacterAttributes(8, 5, attr5, false);

    MutableAttributeSet attr6 = new SimpleAttributeSet();
    StyleConstants.setStrikeThrough(attr6, true);
    /* 27文字目から5文字分だけ取り消し線を引く */
    doc.setCharacterAttributes(27, 5, attr6, false);
  }
}

実行結果は下記のようになります。

これでスタイルの変更はできるようになりましたが、次は自分で選択した箇所の文書のスタイルを変更できるようにしていきます。

( Written by Tatsuo Ikura )

関連記事 (一部広告含む)