標準出力表示TextAreaを作る
では、実際に標準出力を表示するコンポーネントを作ってみましょう。表示に利用するのはTextAreaコンポーネントです。これをextendsして作ることにしましょう。また、PrintStreamで出力したテキストをそのままテキストとして取得するためにはByteArrayOutputStreamが便利そうです。これは文字通りbyte配列にテキストなどを出力するストリームです。
PrintStreamは、他のOutputStreamを引数にしてインスタンスを作成します。そしてPrintStreamでprint/printlnなどでテキストを出力すると、最終的にはそのOutputStreamのwriteメソッドを呼び出してテキストを出力するようになっています。ということは、OutputStreamを継承したクラスを作り、そのwriteメソッドをオーバーライドして独自の処理を定義しておけば、出力時の処理を変えてしまうことができそうですね。
TextArea内にあるPrintStreamを介してByteArrayOutputStreamに出力がされ、その結果をTextAreaに表示するようにすれば標準出力をGUIで表示できます。 |
では、標準出力を表示するコンポーネントクラス「OutputTextArea」と、その内部で利用される出力ストリームクラス「TextAreaOutputStream」を作成してみましょう。(なお、packageは省略してあります)
import java.awt.*;
import java.io.*;
public class OutputTextArea extends TextArea {
private TextAreaOutputStream out;
public OutputTextArea() throws HeadlessException {
super();
this.setEditable(false);
out = new TextAreaOutputStream(this);
}
public void setToSystemOut(){
System.setOut(new PrintStream(this.getOut()));
}
public void setToSystemErr(){
System.setErr(new PrintStream(this.getOut()));
}
public TextAreaOutputStream getOut() {
return out;
}
public void flush(){
this.append(out.toString());
out.reset();
}
}
class TextAreaOutputStream extends ByteArrayOutputStream {
private OutputTextArea textarea;
public TextAreaOutputStream(OutputTextArea textarea) {
super();
this.textarea = textarea;
}
public synchronized void write(byte[] b, int off, int len) {
super.write(b, off, len);
textarea.flush();
}
public synchronized void write(int b) {
super.write(b);
textarea.flush();
}
public void write(byte[] b) throws IOException {
super.write(b);
textarea.flush();
}
}
ここではOutputTextAreaについては引数をもたないコンストラクタのみ用意しておきました。TextAreaとして更に使いやすくしたければ、その他のコンストラクタもオーバーライドして用意しておくとよいでしょう。
OutputTextAreaで行っていることは比較的単純ですね。TextAreaOutputStreamインスタンスをフィールドとして用意し、setOut/setErrでTextAreaOutputStreamを設定するためのメソッドを用意してあります。またflushは、TextAreaOutputStreamからテキストを自身の表示テキストの末尾にappendし、ストリームをリセットするものです。このflushを呼び出すことで、その時点でTextAreaOutputStreamに保管されていたテキストが自身に書き出されるわけです。
TextAreaOutputStreamでは、各writeメソッドをオーバーライドし、writeされたらsuper.writeで出力処理をさせた後、OutputTextAreaのflushを呼び出しています。これで、writeされたら自身に出力されたテキストをOutputTextAreaに表示されたテキストの末尾に追加するようになります。
2つのクラスはお互いに連携して動いていますので、使う際には常に2つセットで自分のプログラムに組み込むようにしてください。