RTFへのファイルの保存
では、saveメニューを選んだ際に実行されるwriteToFileメソッドを定義しましょう。RTFへの保存は、javax.swing.text.rtfパッケージの「RTFEditorKit」クラスを利用して行います。このクラスに用意されているメソッドを使い、指定のストリームにRTFデータを出力できます。基本的な手順を整理すると、
- ファイルに保存するためのFileOutputStreamを作成する。
- RTFEditorKitのwriteメソッドを使い、FileOutputStreamに指定範囲の属性付テキストを出力する。
- closeでFileOutputStreamを閉じる。
以上の操作でRTFへの出力を行うことができます。ただし、実際には、ファイルを選択するためのダイアログの利用などの処理が必要となってくるでしょう。では、メソッドを実装してみましょう。
public void writeToFile(){ Document doc = pane.getDocument(); RTFEditorKit rtfkit = new RTFEditorKit(); File file = null; JFileChooser chooser = new JFileChooser(); FileFilter filter = new CustomRTFFilter(); chooser.setFileFilter(filter); int res = chooser.showSaveDialog(this); if (res == JFileChooser.APPROVE_OPTION){ OutputStream out = null; try { file = chooser.getSelectedFile(); out = new FileOutputStream(file); rtfkit.write(out,doc,0,doc.getLength()); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } catch (BadLocationException e) { e.printStackTrace(); } finally { try { out.close(); } catch (IOException e) { e.printStackTrace(); } } } }
ここでは、RTFファイルだけを表示させるのにCustomRTFFilterというフィルタ・クラスを利用しています。これについては後で作成をします。ここでは、必要なオブジェクトとして、テキストデータを管理するDocumentと、保存のためのRTFEditorKitを最初に用意しています。この部分です。
Document doc = pane.getDocument();
RTFEditorKit rtfkit = new RTFEditorKit();
それから、JFileChooserのshowSaveDialogでファイルダイアログを呼び出し、ファイルを選択します。ダイアログの呼び出しは、こんな具合に行っています。
int res = chooser.showSaveDialog(this); if (res == JFileChooser.APPROVE_OPTION){
JFileChooserのshowSaveDialogを呼び出すと、ダイアログが画面に現れます。これはモーダルなので、ダイアログが閉じられるまで処理は停止されます。返された値が、JFileChooser.APPROVE_OPTIONであれば、ファイルが選択されたとみなし処理できるわけです。
JFileChooserから保存するファイルの情報を取得し、RTFEditorKitで保存を行う処理は次のようになります。
file = chooser.getSelectedFile();
out = new FileOutputStream(file);
rtfkit.write(out,doc,0,doc.getLength());
実は、RTFファイルへの保存の部分は、たったこれだけです。ソースコードをよく見ると、処理の大半がJFileChooser関係であることが分かるでしょう。
RFTファイルの読み込み
続いて、RTFファイルを読み込んで表示させる処理に進みましょう。こちらも、基本的な考え方はほぼ同じです。違いは、出力ストリームではなく入力ストリームを使う、という点ぐらいでしょう。流れを整理すると、
- ファイルに保存するためのFileInputStreamを作成する。
- RTFEditorKitのreadメソッドを使い、FileInputStreamから属性付テキストを取り出す。
- closeでFileInputStreamを閉じる。
このようになります。では、こちらもメソッドを実装しましょう。
public void readFromFile(){ StyleContext style = new StyleContext(); DefaultStyledDocument doc = new DefaultStyledDocument(style); RTFEditorKit rtfkit = new RTFEditorKit(); File file = null; JFileChooser chooser = new JFileChooser(); FileFilter filter = new CustomRTFFilter(); chooser.setFileFilter(filter); int res = chooser.showOpenDialog(this); if (res == JFileChooser.APPROVE_OPTION){ InputStream in = null; try { file = chooser.getSelectedFile(); in = new FileInputStream(file); rtfkit.read(in, doc, 0); pane.setDocument(doc); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } catch (BadLocationException e) { e.printStackTrace(); } finally { try { in.close(); } catch (IOException e) { e.printStackTrace(); } } } }
基本的な部分は先のwriteToFileとほとんど同じです。JFileChooserで選択したファイルからRTFデータを読み込み、JTextPaneに表示させる部分だけを見てみると、こんな具合になっています。
file = chooser.getSelectedFile();
in = new FileInputStream(file);
rtfkit.read(in, doc, 0);
pane.setDocument(doc);
RTFEditorKitのreadで、入力ストリームから読み込み、それをDocumentに設定します。そして、このDocumentを改めてJTextPaneに設定すれば、読み込まれたRTFのテキストが表示されるというわけです。
フィルタ・クラスの作成
最後に、RTFファイルを選択するためのフィルタクラスを用意しておきましょう。これは、JFileChooserに設定し、.rtf拡張子のファイルだけが表示されるようにするためのものです。
class CustomRTFFilter extends FileFilter { public boolean accept(File f) { if (f.isDirectory()) { return true; } String fname = f.getName(); int n = fname.lastIndexOf("."); String ext = fname.substring(n); ext = ext.toLowerCase(); if (ext != null) { if (ext.equals(".rtf")){ return true; } else { return false; } } return false; } public String getDescription() { return "RTF"; } }
フィルタ・クラスは、javax.swing.filechooserパッケージの「FileFilter」を継承して作ります。acceptメソッドで、引数に渡されたFileオブジェクトが表示可能かどうかをチェックしboolean値を返すようにします。ここでは、ファイル名の最後が".rtf"ならばtrue、そうでなければfalseを返すようにしてあります。これで、.rtfで終わるファイルだけが選択できるようになるわけです。JFileChooserを利用する際には覚えておきたいクラスですね。
まとめ
今回は、JTextPaneを使って、マルチフォントのテキストを扱うための基本について説明をしました。これで、テキストの一部分のスタイルを変更したり、またマルチフォントのテキストをファイルに読み書きしたりできるようになりました。
このJTextPaneも、表示される情報はモデル・クラスを使って管理していました。このモデル・クラスのように、画面にはまったく表示されない、コンピュータの内部だけであれこれ動いているクラスというのが、Swingではたくさんあります。Swingというと、「GUIのライブラリ」ということで、目に見える部分ばかりに注意がいきがちですが、こうした「見えないクラス」の働きの方が目に見えるコンポーネントよりも何倍も大きいのです。こうしたクラスの扱いに慣れておくのも、Swing上達のポイントと言えるでしょう。


