For Java developers, it’s very common for using these well-known statements:

System.out.print("something");
System.out.println("one more thing");

 

to print some text on the standard output console for the purpose of debugging and testing. However, there would be some cases in which we want the text goes into a Swing component such as a JTextArea, rather than into the standard output console. This article describes how to make that possible with a small example program.

The main idea is based on the two methods provided by the System class:

    • System.setOut(PrintStream): Re-assigns the standard output stream.
    • System.setErr(PrintStream): Re-assigns the standard error output stream.

Create a sub class of OutputStream class like this:

package net.codejava.swing;

import java.io.IOException;
import java.io.OutputStream;

import javax.swing.JTextArea;

/**
 * This class extends from OutputStream to redirect output to a JTextArrea
 * @author www.codejava.net
 *
 */
public class CustomOutputStream extends OutputStream {
	private JTextArea textArea;
	
	public CustomOutputStream(JTextArea textArea) {
		this.textArea = textArea;
	}
	
	@Override
	public void write(int b) throws IOException {
		// redirects data to the text area
        textArea.append(String.valueOf((char)b));
        // scrolls the text area to the end of data
        textArea.setCaretPosition(textArea.getDocument().getLength());
	}
}

 

As we can see, the constructor takes a JTextArea object as argument and overrides the write(int) method from the OutputStream class. In the write() method, we convert the byte to a character and append it to the JTextArea. So everything written to this output stream will be placed into the text area. Then we can re-assign the standard output streams as follows:

JTextArea textArea = new JTextArea(50, 10);
PrintStream printStream = new PrintStream(new CustomOutputStream(textArea)); 
System.setOut(printStream);
System.setErr(printStream);

If we still want to use the standard output streams, we have to keep references to them before re-assigning, for example:

PrintStream standardOut = System.out;
PrintStream standardErr = System.err; 

Following is a sample Swing program that displays a text area with two buttons:

demo program

Clicking on Start button will start a new thread which prints a log statement for every one second. The Clear button will clear the text area.

 

 

Here is code of the program:

package net.codejava.swing;

import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.PrintStream;
import java.util.Date;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;
import javax.swing.text.BadLocationException;

public class TextAreaLogProgram extends JFrame {
	/**
	 * The text area which is used for displaying logging information.
	 */
	private JTextArea textArea;
	
	private JButton buttonStart = new JButton("Start");
	private JButton buttonClear = new JButton("Clear");
	
	private PrintStream standardOut;
	
	public TextAreaLogProgram() {
		super("Demo printing to JTextArea");
		
		textArea = new JTextArea(50, 10);
		textArea.setEditable(false);
		PrintStream printStream = new PrintStream(new CustomOutputStream(textArea));
		
		// keeps reference of standard output stream
		standardOut = System.out;
		
		// re-assigns standard output stream and error output stream
		System.setOut(printStream);
		System.setErr(printStream);

		// creates the GUI
		setLayout(new GridBagLayout());
		GridBagConstraints constraints = new GridBagConstraints();
		constraints.gridx = 0;
		constraints.gridy = 0;
		constraints.insets = new Insets(10, 10, 10, 10);
		constraints.anchor = GridBagConstraints.WEST;
		
		add(buttonStart, constraints);
		
		constraints.gridx = 1;
		add(buttonClear, constraints);
		
		constraints.gridx = 0;
		constraints.gridy = 1;
		constraints.gridwidth = 2;
		constraints.fill = GridBagConstraints.BOTH;
		constraints.weightx = 1.0;
		constraints.weighty = 1.0;
		
		add(new JScrollPane(textArea), constraints);
		
		// adds event handler for button Start
		buttonStart.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent evt) {
				printLog();
			}
		});
		
		// adds event handler for button Clear
		buttonClear.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent evt) {
				// clears the text area
				try {
					textArea.getDocument().remove(0, 
							textArea.getDocument().getLength());
					standardOut.println("Text area cleared");
				} catch (BadLocationException ex) {
					ex.printStackTrace();
				}
			}
		});
		
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setSize(480, 320);
		setLocationRelativeTo(null);	// centers on screen
	}
	
	/**
	 * Prints log statements for testing in a thread
	 */
	private void printLog() {
		Thread thread = new Thread(new Runnable() {
			@Override
			public void run() {
				while (true) {
					System.out.println("Time now is " + (new Date()));
					try {
						Thread.sleep(1000);
					} catch (InterruptedException ex) {
						ex.printStackTrace();
					}
				}
			}
		});
		thread.start();
	}
	
	/**
	 * Runs the program
	 */
	public static void main(String[] args) {
		SwingUtilities.invokeLater(new Runnable() {
			@Override
			public void run() {
				new TextAreaLogProgram().setVisible(true);
			}
		});
	}
}

Related Course: Java Swing (GUI) Programming: From Beginner to Expert 

Learn Swing in Swing: A Beginner's Guide

Submit to DeliciousSubmit to DiggSubmit to FacebookSubmit to Google BookmarksSubmit to StumbleuponSubmit to TechnoratiSubmit to TwitterSubmit to LinkedIn
Attachments:
Download this file (CustomOutputStream.java)CustomOutputStream.java[Java source code]0.6 kB
Download this file (TextAreaLogProgram.java)TextAreaLogProgram.java[Java source code]3 kB