- PR -

コンソール出力について

投稿者投稿内容
toshi
会議室デビュー日: 2007/05/24
投稿数: 11
投稿日時: 2007-05-24 10:51
初心者の質問で、すみませんが教えてください.

XMLの検証やXSLT, XMLからの組版などの処理を制御するGUIをSwingで作成しています.メインのウィンドウにはメニューと、コンソール出力用のJTextAreaを配置します.もう一つのパラメータウィンドウには、各種の処理のパラメータと処理の実行ボタンを配置しています.

実行ボタンを押すと処理が開始されます.処理の各段階では、実行状況をユーザーに知らせるためにSystem.out.println()などでログをコンソール出力しています.このコンソール出力は、以下のコードでメインウィンドウのJTextAreaに行くようにしています.

JTextArea jTextAreaMain = new JTextArea();
...
JTextAreaOutputStream jtextAreaOutputStream = new JTextAreaOutputStream(jTextAreaMain);
PrintStream printStream = new PrintStream(jtextAreaOutputStream);
System.setOut(printStream);
System.setErr(printStream);

// JTextAreaOutputStreamクラス
public class JTextAreaOutputStream extends ByteArrayOutputStream {
private JTextArea jtextArea;

public JTextAreaOutputStream(JTextArea jtextArea){
super();
this.jtextArea=jtextArea;
}

public synchronized void write(byte[] b, int off, int len){
super.write(b, off, len);
appendString();
}

public synchronized void write(byte[] b) throws IOException{
super.write(b);
appendString();
}

public synchronized void write(int b){
super.write(b);
appendString();
}
/**
* Append text to JTextArea and reset caret position
*/
private void appendString(){
jtextArea.append(this.toString());
int length=jtextArea.getDocument().getLength();
jtextArea.setCaretPosition(length);
this.reset();
}
}

ところが実際に実行ボタンを押して処理を実行してみると、JTextAreaへの表示と処理の進行が同期してくれません.処理が終了したとたんに一気にJTextAreaへ実行ログが表示されてしまいます.

処理の中には10〜20分かかるものもあるので、これではユーザーはダンマリと勘違いしてしまうでしょう.System.out.println()とJTextAreaへの描画を同期させるにはどのようにしたら良いのでしょうか?

もし御存知の方がおられましたらアドバイスをお願いいたします.

以上
あすか
ぬし
会議室デビュー日: 2006/07/12
投稿数: 309
投稿日時: 2007-05-24 11:17
http://java.sun.com/j2se/1.5.0/ja/docs/ja/api/java/io/PrintStream.html#PrintStream(java.io.OutputStream)

コンストラクタの詳細

PrintStream
public PrintStream(OutputStream out)新しい PrintStream を作成します。このストリームは、自動的にフラッシュすることはありません。
toshi
会議室デビュー日: 2007/05/24
投稿数: 11
投稿日時: 2007-05-24 11:38
ご回答ありがとうございます.
確かにそのとおりでした.

ところが

PrintStream printStream = new PrintStream(jtextAreaOutputStream, true);

に変更してみても現象は変わりません.相変わらず最後にまとまってログが表示されてしまいます.

どうしたものか困っています.

以上
飴@玉
会議室デビュー日: 2006/09/12
投稿数: 4
投稿日時: 2007-05-24 11:58
JTextAreaをAWTのTextAreaに変更すればうまくいくと思います。
理由はSwing とスレッド 辺りを確認してみてください。
朝日奈ありす
大ベテラン
会議室デビュー日: 2007/05/02
投稿数: 189
お住まい・勤務地: 最北の地
投稿日時: 2007-05-24 12:10
コンソールがある場合はコンソールのイベントで
そうでない場合は直接ログを
これが一番楽かも
nagise
ぬし
会議室デビュー日: 2006/05/19
投稿数: 1141
投稿日時: 2007-05-24 14:04
JTextArea.append()をjavax.swing.SwingUtilities.invokeLater()で処理するか、
JTextAreaのvalidate()を呼び出して見たら改善しませんかね?

ところでByteArrayOutputStreamの継承クラスのthis.toString()を
append()していくとおかしな挙動になりませんか?

write(1);
write(2);
write(3);

としたら
112123
と表示されるような気がするのですが。
toshi
会議室デビュー日: 2007/05/24
投稿数: 11
投稿日時: 2007-05-24 14:29
皆様いろいろと参考になる情報をありがとうございます.

>ところでByteArrayOutputStreamの継承クラスのthis.toString()を
>append()していくとおかしな挙動になりませんか?

表示されている結果を見る限り、大丈夫なようです.super.write();ではバッファに格納するだけだからでしょうか?

現在いただいた情報を元に必死に修正方法を考えております.

# 超初心者には荷が重いですが,,,

SwingUtilities.invokeLater()でやりたいところです.TextAreaに代えてみたのですが、どういうわけかメニューをクリックしても表示がされなくなってしまい影響が大きいので...


以上
unibon
ぬし
会議室デビュー日: 2002/08/22
投稿数: 1532
お住まい・勤務地: 美人谷        良回答(20pt)
投稿日時: 2007-05-24 14:48
引用:

toshiさんの書き込み (2007-05-24 10:51) より:
処理の中には10〜20分かかるものもあるので、これではユーザーはダンマリと勘違いしてしまうでしょう.System.out.println()とJTextAreaへの描画を同期させるにはどのようにしたら良いのでしょうか?


良くは見ていませんが、普通、長い処理中に描画をおこなうためには、その処理はマルチスレッドで動かさないといけません。
(Thread や Runnable がキーワードになります。)

おそらく System.out.println() には即時に表示されているのに、JTextArea には即時に表示されないことを疑問に思われているのだろうと推測しますが、System.out.println() は表示が別扱いになっていて特殊な機構でそうなっていると思ったほうが良いです。

--
unibon {B73D0144-CD2A-11DA-8E06-0050DA15BC86}

スキルアップ/キャリアアップ(JOB@IT)