JavaFX | Redirect console output to TextArea

In this tutorial, you will learn to redirect console output to textarea in JavaFX application. This is a very useful implementation for most of the applications. I have explained the whole implementation step by step with the help of a diagram.

See the below diagram, this is showing the core logic to redirect console output to the text area.
Basically, I have created a new PrintStream object with the help of PipedOutputStream and PipedInputstream and then associated it with the Out object of the system class. After that, a reader thread is created and executed as a daemon thread to read the input stream from pipedoutputstream and convert this byte stream to text then write inside JavaFX TextArea.
Please watch the below video tutorial for a better understanding.

Source code download link for the files used in the demo project:

1) FXMLDocument.fxml

 <?xml version=”1.0″ encoding=”UTF-8″?>
<?import javafx.scene.text.*?>
<?import java.lang.*?>
<?import java.util.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<AnchorPane id=”AnchorPane” fx:id=”myAnchorPane” prefHeight=”367.0″ prefWidth=”467.0″ xmlns=”http://javafx.com/javafx/8″ xmlns:fx=”http://javafx.com/fxml/1″ fx:controller=”javafxconsoletextarea.FXMLDocumentController”>
    <children>
        <Button fx:id=”button” layoutX=”142.0″ layoutY=”87.0″ onAction=”#handleButtonAction” text=”Click to execute something” />
        <Label fx:id=”label” layoutX=”11.0″ layoutY=”127.0″ minHeight=”16″ minWidth=”69″ text=”Console Output”>
         <font>
            <Font name=”System Bold” size=”12.0″ />
         </font></Label>
      <TextArea fx:id=”textAreaUI” editable=”false” layoutX=”11.0″ layoutY=”147.0″ prefHeight=”206.0″ prefWidth=”443.0″ />
      <Pane layoutX=”2.0″ layoutY=”3.0″ prefHeight=”39.0″ prefWidth=”460.0″ style=”-fx-background-color: blue;”>
         <children>
            <Label layoutX=”14.0″ layoutY=”5.0″ prefHeight=”27.0″ prefWidth=”344.0″ text=”Redirecting Console output to TextArea” textFill=”#fffefe”>
               <font>
                  <Font name=”System Bold Italic” size=”18.0″ />
               </font>
            </Label>
         </children>
      </Pane>
    </children>
</AnchorPane>

2)FXMLDocumentController.java

package javafxconsoletextarea;
import java.net.URL;
import java.util.ResourceBundle;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.TextArea;
public class FXMLDocumentController implements Initializable {
    @FXML
    private TextArea textAreaUI;
    static TextArea staticTxtArea;
    @FXML
    private void handleButtonAction(ActionEvent event) {
        // these will be redirected to textArea on GUI
        System.err.println(“@@@@ERROR: This is error”);
        System.out.println(“####OUTPUT : THIS IS ERROR”);
        //generating an exception to print on console
        try
        {
          int x  = 5/0;
        }
        catch(Exception ex)
        {
          ex.printStackTrace();
         // System.out.println(ex.getMessage());
        }
    }
    @Override
    public void initialize(URL url, ResourceBundle rb) {
       staticTxtArea = textAreaUI;
  }
}

3) JavaFXConsoleTextArea.java

package javafxconsoletextarea;
import java.io.IOException;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
import java.io.PrintStream;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.event.EventHandler;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.TextArea;
import javafx.stage.Stage;
import javafx.stage.WindowEvent;
public class JavaFXConsoleTextArea extends Application {
    private final PipedInputStream pipeIn = new PipedInputStream();
    private final PipedInputStream pipeIn2 = new PipedInputStream();
    Thread errorThrower;
    private Thread reader;
    private Thread reader2;
    boolean quit;
    private TextArea txtArea;
    @Override
    public void start(Stage stage) throws Exception {
        Parent root = FXMLLoader.load(getClass().getResource(“FXMLDocument.fxml”));
        //Console myConsole = new Console();
        Scene scene = new Scene(root);
        stage.setScene(scene);
        stage.show();
        txtArea = FXMLDocumentController.staticTxtArea;
        //Thread execution for reading output stream
        executeReaderThreads();
        //Thread closing on stag close event
        stage.setOnCloseRequest(new EventHandler<WindowEvent>() {
        @Override
        public void handle(WindowEvent e) {
        closeThread();
        Platform.exit();
        System.exit(0);
        }
        });
    }
    //method to handle thread closing on stage closing
    synchronized void closeThread()
    {
       System.out.println(“Message: Stage is closed.”);
       this.quit = true;
       notifyAll();
       try { this.reader.join(1000L); this.pipeIn.close(); } catch (Exception e) {
       }try { this.reader2.join(1000L); this.pipeIn2.close(); } catch (Exception e) {
       }System.exit(0);
    }
    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        launch(args);
    }
    public void executeReaderThreads()
    {
      try
      {
      PipedOutputStream pout = new PipedOutputStream(this.pipeIn);
      System.setOut(new PrintStream(pout, true));
      }
      catch (IOException io)
      { }
      catch (SecurityException se)
      { }
    try
    {
      PipedOutputStream pout2 = new PipedOutputStream(this.pipeIn2);
      System.setErr(new PrintStream(pout2, true));
    }
    catch (IOException io)
    {
    }
    catch (SecurityException se)
    {
    }
ReaderThread obj = new ReaderThread(pipeIn, pipeIn2, errorThrower, reader, reader2, quit, txtArea);
    }
}

4) ReaderThread.java

 
package javafxconsoletextarea;
import java.io.IOException;
import java.io.PipedInputStream;
import javafx.scene.control.TextArea;
public class ReaderThread implements Runnable{
    private final PipedInputStream pipeIn ;
    private final PipedInputStream pipeIn2 ;
    Thread errorThrower;
    private Thread reader;
    private Thread reader2;
    private boolean quit;
    private TextArea txtArea;
    ReaderThread(PipedInputStream pinInput1, PipedInputStream pinInput2, Thread errorThrower1, Thread reader11, Thread reader22, boolean newflag, TextArea txtArea1)
    {
       pipeIn = pinInput1;
       pipeIn2 = pinInput2;
       errorThrower = errorThrower1;
       reader = reader11;
       reader2 = reader22;
       quit =  newflag;
       txtArea = txtArea1;
    this.quit = false;
    this.reader = new Thread(this);
    this.reader.setDaemon(true);
    this.reader.start();
    this.reader2 = new Thread(this);
    this.reader2.setDaemon(true);
    this.reader2.start();
    this.errorThrower = new Thread(this);
    this.errorThrower.setDaemon(true);
    this.errorThrower.start();
    }
  public synchronized void run()
  {
    try
    {
      while (Thread.currentThread() == this.reader) {
        try {
             wait(100L);
        }
        catch (InterruptedException ie)
        {
            System.out.println(“I am in thread 1”);
        }
        if (this.pipeIn.available() != 0)
        {
          String input = readLine(this.pipeIn); //reading console output stream from pipedinputstream
          this.txtArea.appendText(input);
        }
        if (this.quit) return;
      }
      //while loop starting
      while (Thread.currentThread() == this.reader2) {
        try {
          wait(100L);
        }
        catch (InterruptedException ie)
        {
        }
        if (this.pipeIn2.available() != 0)
        {
          String input = readLine(this.pipeIn2);
           this.txtArea.appendText(input);
        }
        if (this.quit) return; //if some one closed the stage then this check will be performed every time, if true
        //thread execution will be stopped.
      } //while loop ending here
    }
    catch (Exception e)
    {
    }
    if (Thread.currentThread() == this.errorThrower) {
      try {
        wait(800L);
      }
      catch (InterruptedException ie) {
      }
      System.out.println(“****************************Console Started Successfully********************************************************”);
    }
  }
  public synchronized String readLine(PipedInputStream in)
    throws IOException
  {
    String input = “”;
    do
    {
      int available = in.available();
      if (available == 0) break;
      byte[] b = new byte[available];
      in.read(b);
      input = input + new String(b, 0, b.length);
    }while ((!input.endsWith(“n”)) && (!input.endsWith(“rn”)) && (!this.quit));
    return input;
  }
}
If you have any doubts so please ask in comment box below on this post. I will try my best to reply as soon as possible.
Happy Coding Guys.  🙂

Leave a Comment