Problem logging to a JTextArea

Hi, I am trying to use java logging to write logging to the standard console and to a JTextArea component within the application. The program creates a new logger using a PipedOutputStream as the OutputStream, the console class starts another thread to listen to the corresponding PipedInputStream every 5 seconds and update the JTextArea, I am having two problems with it.

1. The standard console (System.err) is receiving the log message so I assume the log is being published in the StreamHandler but the PipedInputStream is not receiving anything, I also tried using ByteArrayOutputStream instead and still didnt receive anything.

2. i can only see how to replace the text in a textarea, is there a way to just add text.

import java.io.IOException;

import java.io.InputStream;

import java.io.OutputStream;

import java.io.PipedInputStream;

import java.io.PipedOutputStream;

import java.util.logging.Logger;

import java.util.logging.SimpleFormatter;

import java.util.logging.StreamHandler;

import javax.swing.JFrame;

import javax.swing.JTextArea;

import javax.swing.SwingUtilities;

publicclass MainTest

{

publicstaticvoid main( String[] args )

{

Logger userInfoLogger = Logger.getLogger(Main.class.getName());

userInfoLogger.addHandler(new StreamHandler (Console.getInstanceOf().getOutputStream(),new SimpleFormatter()));

userInfoLogger.severe("ExampleLogMessage");

JFrame frame =new JFrame();

frame.add(Console.getInstanceOf().getConsoleWindow());

frame.pack();

frame.setVisible(true);

}

}

/** Console provides information to user */

class Console

{

privatestatic Console console;

private JTextArea consoleWindow;

private PipedOutputStream baos;

private PipedInputStream bais;

private Console()

{

consoleWindow =new JTextArea(5,120);

consoleWindow.setAutoscrolls(true);

consoleWindow.setLineWrap(true);

consoleWindow.setEditable(false);

baos =new PipedOutputStream();

bais =new PipedInputStream();

try

{

baos.connect(bais);

}

catch(Exception e)

{

thrownew RuntimeException("Problem connecting error pipes");

}

startListening();

}

publicstatic Console getInstanceOf()

{

if(console==null)

{

console =new Console();

}

return console;

}

public OutputStream getOutputStream()

{

return baos;

}

public InputStream getInputStream()

{

return bais;

}

public JTextArea getConsoleWindow()

{

return consoleWindow;

}

privatevoid startListening()

{

Thread thread =new Thread()

{

publicvoid run()

{

while(true)

{

try

{

Thread.sleep(5000);

System.out.println("running test");

try

{

int i = Console.this.getInputStream().read();

System.out.println("Read"+i);

SwingUtilities.invokeLater(new Runnable()

{

publicvoid run()

{

Console.this.consoleWindow.setText("hello");

}

});

}

catch(IOException ioe)

{

ioe.printStackTrace();

}

}

catch(InterruptedException ie)

{

ie.printStackTrace();

}

}

}

};

thread.start();

}

}

[6850 byte] By [paultaylora] at [2007-10-3 3:16:13]
# 1
2.setText(getText() + newText) orgetDocument().setText(getText().length(), newText, null)
LundqvistEa at 2007-7-14 21:07:36 > top of Java-index,Desktop,Core GUI APIs...
# 2
Did you mean .insertString in the second example?
paultaylora at 2007-7-14 21:07:36 > top of Java-index,Desktop,Core GUI APIs...
# 3

I think you meant insertString rather than setText, and it's probably better to do

Document doc = textArea.getDocument();

doc.insertString( doc.getLength(), newText, null );

so you don't end up constructing a new String simply to get its length and discard it.

JayDSa at 2007-7-14 21:07:36 > top of Java-index,Desktop,Core GUI APIs...
# 4

There is no need to sleep for 5 seconds. Use a BufferedReader it will block waiting for input. Then you simply loop reading a line at a time. There are examples posted in the forum that already do this.

If you want to add text to the text area the standard way to do this is to use the append(...) method.

camickra at 2007-7-14 21:07:36 > top of Java-index,Desktop,Core GUI APIs...
# 5

Thanks for the replies, the following code works although not sure its the best way of doing things, I had to extend Streamhandler to perform a flush() on the publish() method in order to get any data through to the input pipe, i also extended SimpleFormatter because I want every message to only be one line.

I also tried using a BufferedReader but it didnt work. I think it was because it was in a loop whereby either there was data in the pipe or there wasnt in which case it would stop, and it was tring to update the text area for every line, I just want it to update the text area once on every invocation with whatever is in the stream, and I need it to check throughout the lifetime of the program.

import java.io.BufferedReader;

import java.io.IOException;

import java.io.InputStream;

import java.io.InputStreamReader;

import java.io.OutputStream;

import java.io.PipedInputStream;

import java.io.PipedOutputStream;

import java.io.PrintWriter;

import java.io.StringWriter;

import java.text.MessageFormat;

import java.util.Date;

import java.util.logging.Formatter;

import java.util.logging.LogRecord;

import java.util.logging.Logger;

import java.util.logging.SimpleFormatter;

import java.util.logging.StreamHandler;

import javax.swing.JFrame;

import javax.swing.JTextArea;

import javax.swing.SwingUtilities;

public class MainTest

{

public static void main( String[] args ) throws Exception

{

Logger userInfoLogger = Logger.getLogger(Main.class.getName());

userInfoLogger.addHandler(new GuiConsoleHandler (Console.getInstanceOf().getOutputStream(),new GuiConsoleFormatter()));

userInfoLogger.severe("ExampleLogMessage");

JFrame frame = new JFrame();

frame.add(Console.getInstanceOf().getConsoleWindow());

frame.pack();

frame.setVisible(true);

for(int i =0; i< 10;i++)

{

Thread.sleep(2000);

userInfoLogger.severe("ExampleLogMessage:"+i);

}

}

}

/** Console provides information to user */

class Console

{

private static Console console;

private JTextArea consoleWindow;

private PipedOutputStream baos;

private PipedInputStream bais;

private Console()

{

consoleWindow = new JTextArea(5,120);

consoleWindow.setAutoscrolls(true);

consoleWindow.setLineWrap(true);

consoleWindow.setEditable(false);

baos = new PipedOutputStream();

bais = new PipedInputStream();

try

{

baos.connect(bais);

}

catch(Exception e)

{

throw new RuntimeException("Problem connecting error pipes");

}

startListening();

}

public static Console getInstanceOf()

{

if(console==null)

{

console = new Console();

}

return console;

}

public OutputStream getOutputStream()

{

return baos;

}

public InputStream getInputStream()

{

return bais;

}

public JTextArea getConsoleWindow()

{

return consoleWindow;

}

private void startListening()

{

Thread thread = new Thread()

{

public void run()

{

try

{

while(true)

{

if(Console.this.getInputStream().available()>0)

{

byte[] vals = new byte[Console.this.getInputStream().available()];

Console.this.getInputStream().read(vals);

final String data = new String(vals);

SwingUtilities.invokeLater(new Runnable()

{

public void run()

{

try

{

Console.this.consoleWindow.append(data);

}

catch(Exception e )

{

e.printStackTrace();

}

}

});

}

Thread.sleep(5000);

}

}

catch (Throwable _t)

{

_t.printStackTrace();

}

}

};

thread.start();

}

}

class GuiConsoleHandler extends StreamHandler

{

public GuiConsoleHandler(OutputStream out, Formatter formatter)

{

super(out,formatter);

}

public void publish( LogRecord record )

{

super.publish( record );

flush();

}

}

class GuiConsoleFormatter extends SimpleFormatter

{

private final static String format = "{0,date} {0,time}";

Date dat = new Date();

private Object args[] = new Object[1];

private MessageFormat formatter;

private String lineSeparator = (String) java.security.AccessController.doPrivileged(

new sun.security.action.GetPropertyAction("line.separator"));

public synchronized String format(LogRecord record)

{

StringBuffer sb = new StringBuffer();

dat.setTime(record.getMillis());

args[0] = dat;

StringBuffer text = new StringBuffer();

formatter = new MessageFormat(format);

formatter.format(args, text, null);

sb.append(text);

sb.append(": ");

String message = formatMessage(record);

sb.append(record.getLevel().getLocalizedName());

sb.append(": ");

sb.append(message);

sb.append(lineSeparator);

if (record.getThrown() != null)

{

try

{

StringWriter sw = new StringWriter();

PrintWriter pw = new PrintWriter(sw);

record.getThrown().printStackTrace(pw);

pw.close();

sb.append(sw.toString());

}

catch (Exception ex)

{

}

}

return sb.toString();

}

paultaylora at 2007-7-14 21:07:36 > top of Java-index,Desktop,Core GUI APIs...