Redirect standard output streams to JTextArea
- Details
- Written by Nam Ha Minh
- Last Updated on 06 July 2019   |   Print Email
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:
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); } }); } }
Other Java Swing Tutorials:
- Java Swing Hello World Tutorial for Beginners Using Text Editor
- JFrame basic tutorial and examples
- JPanel basic tutorial and examples
- JLabel basic tutorial and examples
- JTextField basic tutorial and examples
- JButton basic tutorial and examples
- JComboBox basic tutorial and examples
- JCheckBox basic tutorial and examples
- JList basic tutorial and examples
Comments
thankyou!!!!!!!!!
i will use it many times from now on