2012-02-13 3 views
1

JTextAreaを使用して「コンソール」で作業していますが、すべてがうまくいきます。Java:BufferedStreamsとイベントハンドラー

私はここでStackoverflowで見つけたクラスの修正版を使用しています。

import java.io.*; 
import javax.swing.*; 

public class textareaStream extends OutputStream { 

//************************* 
//* Parameters 
//************************* 
private JTextArea textArea; // target text area 
private byte[] aByte;  // array for write(int val); 

//************************* 
//* Constructor 
//************************* 
public textareaStream(JTextArea ta) { 
    textArea=ta; 
    aByte=new byte[1]; 
} 


//************************* 
//* Writing methods 
//************************* 
public void write(int val) { 
    aByte[0]=(byte)val; 
    write(aByte,0,1); 
} 

public void write(byte[] ba) { 
    write(ba,0,ba.length); 
} 

public synchronized void write(byte[] ba,int str,int len) { 
    try { 
     for(int xa=0; xa<10; xa++) { 
      try { 
       textArea.append(new String(ba,str,len)); 
       break; 
      } catch(Throwable thr) { 
       if (xa==9) { 
        thr.printStackTrace(); 
       } else { 
        Thread.sleep(200); 
       } 
      } 
     } 
    } catch(Throwable thr) { 
     CharArrayWriter caw=new CharArrayWriter(); 
     thr.printStackTrace(new PrintWriter(caw,true)); 
     textArea.append(System.getProperty("line.separator","\n")); 
     textArea.append(caw.toString()); 
    } 
} 
} 

「書き込み」メソッドがイベントハンドラから呼び出された場合を除いて、これは素晴らしい方法です。

イベントハンドラでは、イベントが終了するまでテキストがテキストエリアに書き込まれません。私が望むのは、コマンドが実行されるときにテキストがコンソールに書き込まれることです(これは特に時間のかかるコマンドに必要です)。つまり、ユーザーがEnterキーを押すと、JTextAreaにデータを印刷している間に長いプロセスが実行されますが、以降のテキストはまで表示されません。

誰も私がこれを回避する方法について考えている人はいますか?

答えて

1

あなたが正しく理解している場合は、イベントハンドラ内からクラスを使用しており、そこでwriteメソッドを呼び出しています。その場合は、SwingUtilities.invokeLaterメソッドを使用できます。例えば、これを参照してください。

http://www.javamex.com/tutorials/threads/invokelater.shtml

基本的に、あなたはこれらの線に沿ってヘルパーメソッドを作成したい:instanceはあなたtextareaStreamクラスのインスタンスである

private void writeOnEDT(final byte[] ba, final int str, final int len) { 
    SwingUtilities.invokeLater(new Runnable() { 
    public void run() { 
     instance.write(ba, str, len); 
    } 
    }); 
} 

。これを同じクラスに入れる場合は、instance.を削除し、writeの代わりにwriteOnEDTを使用すると正しく動作するはずです。

長時間実行されているジョブであれば、ではなく、がEDTで実行する必要があります。そうでないと、すべてのイベントアクティビティが待機します。 threadsまたはexecutors(これも参照:http://www.baptiste-wicht.com/2010/09/java-concurrency-part-7-executors-and-thread-pools/も参照)を使用してこれを達成できます。これは、あなたが解決しようとしている問題に大きく依存します。

スイングGUIクラスのメソッドは、常にEDT threadで呼び出す必要があります。これらは、詳細な説明については、あなたが興味を持っている場合:

一つの文体の事 - あなたのクラスtextareaStreamの名前。これは、Javaクラスが大文字で始まる事実上の標準です。

+0

ありがとうございました!エグゼキュータとスレッドプールの記事は、まさに私が探していたものです。それは魅力のように働く。答えに書かれた細部のレベル、スタイルノートさえ本当にありがたいです。 – Jason

+0

おかげでジェイソン、助けてうれしい! –

関連する問題