選択されたテキストのスタイル変更
今の例では、決まった文字に対してスタイルを設定していました。では、一歩進んで選択されたテキストに対して処理を行うようにしてみましょう。
スタイルの設定に使った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); }

ここでは、単に選択されたテキストにスタイルを設定しているだけなので、caretUpdateでは、イベントが発生したJTextComponent(JTextPaneのスーパークラス)のgetSelectionStartとgetSelectionEndで選択開始位置と終了位置をそれぞれフィールドに設定しているだけです。まぁ、単に決まった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 Test、open、saveといった3つのメニュー項目が用意できました。ここでは、MenuItemのsetActionCommandでそれぞれアクションコマンドを設定してあります。actionPerformedでは、これをgetActionCommandで取得し、アクションコマンドに応じてメソッドを呼び出すようにしてあります。
