I have a class (shown below) that extends JPanel
and contains a JTextPane
. I want to redirect System.out
and System.err
t
Piped streams always confuse me, which is why my Message Console solution doesn't use them. Anyway here is my attempt at a console using piped streams. A couple of differences:
a) it uses a JTextArea because a JTextArea is more efficient than a JTextPane for just displaying text. Of course if you intend to add attributes to the text then you need a text pane.
b) this solution uses Threads. I'm sure I read somewhere that this was necessary to prevent blocking of the output. Anyway it works in my simple test case.
import java.io.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.text.*;
public class Console implements Runnable
{
JTextArea displayPane;
BufferedReader reader;
private Console(JTextArea displayPane, PipedOutputStream pos)
{
this.displayPane = displayPane;
try
{
PipedInputStream pis = new PipedInputStream( pos );
reader = new BufferedReader( new InputStreamReader(pis) );
}
catch(IOException e) {}
}
public void run()
{
String line = null;
try
{
while ((line = reader.readLine()) != null)
{
// displayPane.replaceSelection( line + "\n" );
displayPane.append( line + "\n" );
displayPane.setCaretPosition( displayPane.getDocument().getLength() );
}
System.err.println("im here");
}
catch (IOException ioe)
{
JOptionPane.showMessageDialog(null,
"Error redirecting output : "+ioe.getMessage());
}
}
public static void redirectOutput(JTextArea displayPane)
{
Console.redirectOut(displayPane);
Console.redirectErr(displayPane);
}
public static void redirectOut(JTextArea displayPane)
{
PipedOutputStream pos = new PipedOutputStream();
System.setOut( new PrintStream(pos, true) );
Console console = new Console(displayPane, pos);
new Thread(console).start();
}
public static void redirectErr(JTextArea displayPane)
{
PipedOutputStream pos = new PipedOutputStream();
System.setErr( new PrintStream(pos, true) );
Console console = new Console(displayPane, pos);
new Thread(console).start();
}
public static void main(String[] args)
{
JTextArea textArea = new JTextArea();
JScrollPane scrollPane = new JScrollPane( textArea );
JFrame frame = new JFrame("Redirect Output");
frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
frame.getContentPane().add( scrollPane );
frame.setSize(200, 100);
frame.setVisible(true);
Console.redirectOutput( textArea );
final int i = 0;
Timer timer = new Timer(1000, new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
System.out.println( new java.util.Date().toString() );
System.err.println( System.currentTimeMillis() );
}
});
timer.start();
}
}
In the following link you can find the MessageConsole class that someone mentioned. I implemented a software and used this solution and it works perfect for me. I used the Netbeans design tool, so the code regarding the visual appearance of the JTextPane is a bit cumbersome, so I'm not going to place it here.
JTextPane jTextPane = new JTextPane();
MessageConsole console = new MessageConsole(jTextPane);
/*
This parameters are optional, but if you are looking for a solution with JTextPane it is because you need them, at least color.
*/
console.redirectErr(Color.RED, null);
console.redirectOut();
//some event
private void jButton1ActionPerformed(ActionEvent evt) {
/*
In this event I execute a function of my business.
I put it in a thread so that it does not block the graphical interface.
There are many calls to System.out.println() and System.err.println()
*/
BusinessClass bc = new BusinessClass();
Runnable runnable = () -> {
bc.someBusinessFn();
};
thread = new Thread(runnable);
thread.start();
}
//My main method
public static void main(String args[]) {
/* Create and display the GUI */
EventQueue.invokeLater(() -> {
new MyJFrame().setVisible(true);
});
}
Edit
Sorry, I did not realize that in the response similar to this, they had put the link to the MessageConsole class. I didn't see it and I also wanted to show my solution.
Message Console class does this for you.
Edit:
Here is a simple test class:
import java.io.*;
import java.awt.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.text.*;
public class MessageConsoleTest
{
public static int counter;
public static void main(String[] args)
throws Exception
{
JTextComponent textComponent = new JTextPane();
JScrollPane scrollPane = new JScrollPane( textComponent );
JFrame.setDefaultLookAndFeelDecorated(true);
JFrame frame = new JFrame("Message Console");
frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
frame.getContentPane().add( scrollPane );
frame.setSize(400, 120);
frame.setVisible(true);
MessageConsole console = new MessageConsole(textComponent);
console.redirectOut();
console.redirectErr(Color.RED, null);
Timer timer = new Timer(1000, new java.awt.event.ActionListener()
{
public void actionPerformed(java.awt.event.ActionEvent e)
{
System.out.println( new java.util.Date().toString() );
}
});
timer.start();
Thread.sleep(750);
Timer timer2 = new Timer(1000, new java.awt.event.ActionListener()
{
public void actionPerformed(java.awt.event.ActionEvent e)
{
System.err.println( "Error Message: " + ++counter);
}
});
timer2.start();
}
}