2016-08-31 7 views
3

JavaFXのTextAreaにSLF4Jによって記録されたエラーを表示したいと思います。私はこれまで持っていることであるappender logback-のtest.xml 中:JavaFXのSLF4JログをTextAreaにリダイレクト

<appender name="err" class="logtest.AppTA"> 
    <filter class="logtest.ErrFilter" /> 
    <encoder> 
     <pattern>%-4relative [%thread] %-5level %logger{35} - %msg%n</pattern> 
    </encoder> 
</appender> 

TextAreaストリーム受信する準備ができて:

public class Output extends OutputStream{ 
    private final TextArea ta; 
    public Output(TextArea ta) { 
     this.ta = ta; 
    } 
    @Override 
    public void write(int b) throws IOException { 
     if (ta!=null) { 
      ta.appendText(String.valueOf((char) b)); 
     } 
    } 
} 

と追加処理するためのクラス:

public class AppTA extends AppenderBase<ILoggingEvent> { 

    PatternLayoutEncoder encoder; 
    OutputStream os; 

    @Override 
    protected void append(ILoggingEvent event) { 
     try { 
      if (isEncoderInitialized) { 
       this.encoder.doEncode(event); 
      } 
     } catch (IOException e) { 
     } 
    } 

    @Override 
    public void start() { 
     if (this.encoder == null) { 
      addError("No encoder set for the appender named [" + name + "]."); 
      return; 
     } 
     try { 
      encoder.init(os); 
     } catch (IOException ex) { 
      Logger.getLogger(AppTA.class.getName()).log(Level.SEVERE, null, ex); 
     } 
     super.start(); 
    } 

    public PatternLayoutEncoder getEncoder() { 
     return encoder; 
    } 

    public void setEncoder(PatternLayoutEncoder encoder) { 
     this.encoder = encoder; 
    } 
} 

今私が抱えている問題は、私のTextAreaがコントローラクラスにあり、私はそれらをリンクする方法を知らないということですエーテル。特にSLF4Jが独自のインスタンスAppTAを作成したとき、私は本当に私のTextAreaAppTAに渡す方法はありません。

これにはどのように対処できますか?

答えて

3

この回答は、基本的なログフレームワークがログバックされているかどうかによって異なります。 SLF4Jは一度に1つのロギング実装しかサポートしていないため、インプリメンテーションにとらわれない方法で解決できるとは思いません。

この問題を解決する最も簡単な方法は、独自のアペンダーを作成して静的状態を利用して、アプリケーション全体のストリームにアクセスできるようにすることです。
以下は、出力ストリームをいつでも静的に設定できるアペンダの基本的な例を示します。
これにはいくつかの制限があります。主に一度に1つの出力ストリームしか処理できないため、複数のサポートに拡張するのは難しくありません。

ログボタンをクリックすると、情報とエラーメッセージがログに記録されます。すべての出力はstdoutに送られますが、エラーメッセージのみがテキスト領域に表示されます。

基本JavaFXアプリケーションクラス

public class Main extends Application { 

    private static final Logger LOG = LoggerFactory.getLogger(Main.class); 

    public static void main(String[] args) { 
     launch(args); 
    } 

    @Override 
    public void start(Stage primaryStage) { 
     Button btn = new Button(); 
     btn.setText("Log stuff"); 
     btn.setOnAction(a-> { 
      LOG.info("This is some info"); 
      LOG.error("This is some error"); 
     }); 

     TextArea textArea = new TextArea(); 
     OutputStream os = new TextAreaOutputStream(textArea); 

     MyStaticOutputStreamAppender.setStaticOutputStream(os); 

     GridPane grid = new GridPane(); 
     grid.add(textArea, 0 ,0); 
     grid.add(btn, 0, 1); 
     primaryStage.setScene(new Scene(grid, 500, 250)); 
     primaryStage.show(); 
    } 

    private static class TextAreaOutputStream extends OutputStream { 

     private TextArea textArea; 

     public TextAreaOutputStream(TextArea textArea) { 
      this.textArea = textArea; 
     } 

     @Override 
     public void write(int b) throws IOException { 
      textArea.appendText(String.valueOf((char) b)); 
     } 
    } 
} 

シンプルなカスタムアペンダクラス

public class MyStaticOutputStreamAppender<E> extends OutputStreamAppender<E> { 


    private static final DelegatingOutputStream DELEGATING_OUTPUT_STREAM = new DelegatingOutputStream(null); 

    @Override 
    public void start() { 
     setOutputStream(DELEGATING_OUTPUT_STREAM); 
     super.start(); 
    } 

    public static void setStaticOutputStream(OutputStream outputStream) { 
     DELEGATING_OUTPUT_STREAM.setOutputStream(outputStream); 
    } 

    private static class DelegatingOutputStream extends FilterOutputStream { 

     /** 
     * Creates a delegating outputstream with a NO-OP delegate 
     */ 
     public DelegatingOutputStream(OutputStream out){ 
      super(new OutputStream() { 
       @Override 
       public void write(int b) throws IOException {} 
      }); 
     } 

     void setOutputStream(OutputStream outputStream) { 
      this.out = outputStream; 
     } 
    } 

} 

Logbackの設定

<?xml version="1.0" encoding="UTF-8"?> 
<configuration> 
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> 
     <encoder> 
      <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{5} - %msg%n</pattern> 
     </encoder> 
    </appender> 

    <appender name="MyCustomAppender" class="example.MyStaticOutputStreamAppender"> 
     <filter class="ch.qos.logback.classic.filter.ThresholdFilter"> 
      <level>ERROR</level> 
     </filter> 
     <encoder> 
      <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{5} - %msg%n</pattern> 
     </encoder> 
    </appender> 

    <root> 
     <appender-ref ref="STDOUT" /> 
     <appender-ref ref="MyCustomAppender" /> 
    </root> 

</configuration> 
+0

はまた、以下の答えを見てみましょう。ありがとう! – alex

1

System.outSystem.errに書き込むようにログバックを設定できます。

アプリケーションのストリーム(setOutsetErr)をテキストエリアに書き込むように設定します。

このソリューションは、コードを変更せずにSLF4Jバインディングで動作するはずです。

基本的には、読み取り専用のJavaFXコンソールを実装します。私はそれをコンパイルするためにいくつかのコードを編集し、それは素晴らしいことだということ以外https://stackoverflow.com/a/9219837/506855

関連する問題