SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

DeveloperZine(デベロッパージン)- エンジニアの意思決定を支える技術情報メディア ProductZine

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

Swing再入門

Swing再入門 マルチフォントへの対応

第4回 JTextPaneを使用したリッチテキストの利用

選択されたテキストのスタイル変更

 今の例では、決まった文字に対してスタイルを設定していました。では、一歩進んで選択されたテキストに対して処理を行うようにしてみましょう。

 スタイルの設定に使ったStyleConstants.setFontSizeなどのメソッド類は、そのスタイル情報を設定する位置と範囲を指定するようになっていました。ということは、選択されたテキストの位置と範囲が分かれば、そこに対してスタイルを設定できるはずです。

 選択されたテキストに関する情報は、javax.swing.eventパッケージの「CaretListener」というインターフェースを使って得ることができます。これは、キャレット位置の変更に関するイベントリスナーです。これをSwingのテキスト編集関係のコンポーネントに組み込むことで、キャレットの位置が変更された際に必要な処理を行うことができます。このインターフェースには、caretUpdateというメソッドが用意されており、キャレット位置が変更されるとこのメソッドが呼び出されるようになっています。

 では、先ほどのフォントサイズを変更する例を、「選択されたテキストのフォントサイズを変更する」というように修正してみましょう。まず、SampleAppクラスにCaretListenerを実装するように宣言部分を修正しておきます。

public class SampleApp extends JFrame 
                       implements ActionListener,CaretListener {

 これで、クラス自身にCaretListenerを実装させることができます。ここでは、選択位置(開始位置と終了位置)を示すフィールドと、選択されているJTextPaneを保管するフィールド用意しておくことにしましょう。そしてコンストラクタでCaretListenerをJTextPaneに組み込むように修正をしておきます。

private int sel_start,sel_end; // 追加するフィールド
private JTextPane sel_textcomp; // 追加するフィールド

public SampleApp(){
    this.setSize(new Dimension(400,300));
    this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    createMenuBar();
    pane = new JTextPane();
    pane.addCaretListener(this); // 追加する行
    JScrollPane scroll = new JScrollPane(pane);
    scroll.setVerticalScrollBarPolicy(
                          JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
    this.add(scroll,BorderLayout.CENTER);
    StyleContext style = new StyleContext();
    DefaultStyledDocument doc = new DefaultStyledDocument(style);
    pane.setDocument(doc);
    pane.setText("Hello Multi Font.");
}

 これで、CaretListenerを利用するようにJTextPaneが修正されました。では、caretUpdateを追加し、actionPerformedを修正してみましょう。

@Override
public void caretUpdate(CaretEvent ev) {
    sel_textcomp = (JTextPane)ev.getSource();
    sel_start = sel_textcomp.getSelectionStart();
    sel_end = sel_textcomp.getSelectionEnd();
}

@Override
public void actionPerformed(ActionEvent e) {
    int fsize = 24; // フォントサイズ
    MutableAttributeSet attr = new SimpleAttributeSet();
    StyleConstants.setFontSize(attr,fsize);
    StyledDocument doc = sel_textcomp.getStyledDocument();
    doc.setCharacterAttributes(sel_start,sel_end - sel_start, attr, true);
}
メニューを選ぶと、選択されたテキストのフォントサイズを24に変更する
メニューを選ぶと、選択されたテキストのフォントサイズを24に変更する

 ここでは、単に選択されたテキストにスタイルを設定しているだけなので、caretUpdateでは、イベントが発生したJTextComponent(JTextPaneのスーパークラス)のgetSelectionStartgetSelectionEndで選択開始位置と終了位置をそれぞれフィールドに設定しているだけです。まぁ、単に決まったJTextPaneの選択位置を得るだけならわざわざcaretUpdateを使わなくてもいいんですが、一つの利用例として、ここでは選択されたJTextPaneを操作するようにしておきました。

 こうしてcaretUpdateで選択範囲と選択されたJTextPaneを取得しておき、そのJTextPaneからStyledDocumentを取得して指定の範囲に適用するようにすれば、「選択されたテキストのスタイルを操作する」ということは案外簡単に行えるようになります。

ファイルアクセス用のメニューの用意

 スタイル情報を含んだテキストは、標準テキストファイルでは保存できません。一般的には、「RTF(Rich Text Format)」と呼ばれるフォーマットで保存することが多いでしょう。では、このRIFファイルへの出力についても試してみましょう。

 ここでは、RTFへの保存と読み込みを行うためのメニューを追加して、そこからメソッドを呼び出すことにしましょう。まず、メニューを実装しているcreateMenuBarを修正し、メニュー項目を選んだ際のactionPerformedにメニューごとの分岐処理を用意しておきます。

public void createMenuBar(){
    JMenuBar menubar = new JMenuBar();
    JMenu menu = new JMenu("Test");
    menubar.add(menu);
    JMenuItem menuitem = new JMenuItem("do test");
    menuitem.setActionCommand("test");
    menuitem.addActionListener(this);
    menu.add(menuitem);
    JMenuItem openitem = new JMenuItem("open");
    openitem.setActionCommand("open");
    openitem.addActionListener(this);
    menu.add(openitem);
    JMenuItem saveitem = new JMenuItem("save");
    saveitem.setActionCommand("save");
    saveitem.addActionListener(this);
    menu.add(saveitem);
    
    this.setJMenuBar(menubar);
}

@Override
public void actionPerformed(ActionEvent e) {
    if (e.getActionCommand().equals("Test")){
        // "do Test"メニューの処理を用意
    }
    if (e.getActionCommand().equals("open")){
        this.readFromFile();
    }
    if (e.getActionCommand().equals("save")){
        this.writeToFile();
    }
}

 これでdo Testopensaveといった3つのメニュー項目が用意できました。ここでは、MenuItemのsetActionCommandでそれぞれアクションコマンドを設定してあります。actionPerformedでは、これをgetActionCommandで取得し、アクションコマンドに応じてメソッドを呼び出すようにしてあります。

次のページ
RTFへのファイルの保存

この記事は参考になりましたか?

Swing再入門連載記事一覧

もっと読む

この記事の著者

掌田 津耶乃(ショウダ ツヤノ)

三文ライター&三流プログラマ。主にビギナーに向けたプログラミング関連の執筆を中心に活動している。※現在、入門ドキュメントサイト「libro」、カード型学習サイト「CARD.tuyano.com」を公開...

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

CodeZine(コードジン)
https://codezine.jp/article/detail/1717 2007/10/10 14:00

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー