Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsWhite Papers
Discussion GroupsFirst AidDatabasesJavaBeansGUIJava 3DVirtual MachineCORBASecurityToolsGeneral
Java DirectoryOpen Source ProjectsSample Book ChaptersUser GroupsWeb Resources
Related Topics
Databases.NETMore Topics ...

Java Forum / GUI / July 2005

Tip: Looking for answers? Try searching our database.

Streaming text to a Swing component...

Thread view: 
Rob McDonald - 07 Jul 2005 20:40 GMT
Is there an easy way to set up a streaming swing console?  (Scrollbars &
read-only clipboard access would be nice.)

I want to be able to set up a text window to act as an output console for my
Swing application.  This application is hidden under something else that
redirects stdout, and the log file isn't very easily accessible....

I want to be able to access this text in a manner analogous to
System.out.println();.

Thanks in advance, please let me know if my request doesn't make sense....

        Rob
Bill Tschumy - 08 Jul 2005 01:39 GMT
> Is there an easy way to set up a streaming swing console?  (Scrollbars &
> read-only clipboard access would be nice.)
[quoted text clipped - 9 lines]
>
>          Rob

I've done this and it was somewhat tricky to get it right.  I've tried to
extract the relevant code in the class below.  Hopefully I didn't cut out
anything essential.  It should give you a huge leg up.

import java.awt.Color;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FilterOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintStream;
import java.text.DateFormat;
import java.util.Date;
import java.util.Vector;

import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;
import javax.swing.text.BadLocationException;
import javax.swing.text.Document;
import javax.swing.text.Element;

public class ConsolePane extends JScrollPane implements Printable
{

   ConsoleInputStream consoleInputStream = new ConsoleInputStream();

   PrintStream consoleOutputStream =
       new PrintStream(new FilteredStream(new ByteArrayOutputStream()));
   Vector listeners = new Vector();
   PrintStream oldErr;
   InputStream oldIn;
   PrintStream oldOut;

   int startOfBuffer;

   MyJTextArea textArea;

   public ConsolePane()
   {
       textArea = new MyJTextArea();
       setViewportView(textArea);
       textArea.setLineWrap(true);
       setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
   }

   
   public void addConsoleListener(ConsoleListener listener)
   {
       listeners.add(listener);
   }

   private void appendNewText(String str)
   {
       if (!EventQueue.isDispatchThread())
           System.err.println("appendNewText called from non-dispatch
thread");
       textArea.append(str);
       int length = textArea.getDocument().getLength();
       textArea.setCaretPosition(length);
       startOfBuffer = length;
       notifyListeners();
   }

   public void clear()
   {
       try
       {
           textArea.getDocument().remove(0, count());
           startOfBuffer = 0;
           consoleOutputStream = new PrintStream(new FilteredStream(new
ByteArrayOutputStream()));
           consoleInputStream = new ConsoleInputStream();
       }
       catch (BadLocationException e)
       {
           System.out.println(e);
       }
   }

   /**
    *  Returns the number of characters in the console buffer.
    */
   private int count()
   {
       return textArea.getDocument().getLength();
   }

   public String getText()
   {
       return textArea.getText();
   }
   

   public void notifyListeners()
   {
       for (int i = 0; i < listeners.size(); i++)
       {
           ConsoleListener listener = (ConsoleListener)
listeners.elementAt(i);
           listener.newText(this);
       }
   }

   public void startErrCapture()
   {
       oldErr = System.err;
       System.setErr(consoleOutputStream);
   }

   public void startInCapture()
   {
       oldIn = System.in;
       System.setIn(consoleInputStream);
   }

   public void startOutCapture()
   {
       oldOut = System.out;
       System.setOut(consoleOutputStream);
   }

   public void stopErrCapture()
   {
       System.setErr(oldErr);
   }

   public void stopInCapture()
   {
       System.setIn(oldIn);
   }

   public void stopOutCapture()
   {
       System.setOut(oldOut);
   }

   
   /**
    *  ConsoleInputStream is a simple extension of ByteArrayInputStream.  It
adds a
    *  growable buffer.
    */
   private class ConsoleInputStream extends ByteArrayInputStream
   {

       /**
        *  Creates a new ConsoleInputStream with an initial buffer size of
20
        */
       public ConsoleInputStream()
       {
           super(new byte[20], 0, 0);
       }

       /**
        * Adds a byte to the InputSteam.
        */
       public void addByte(byte aByte)
       {
           // If the buffer is full, create a new one twice the size and
copy the
           // old stuff over.
           if (count == buf.length)
           {
               byte newBuf[] = new byte[buf.length * 2];
               System.arraycopy(buf, 0, newBuf, 0, buf.length);
               buf = newBuf;
           }

           // Add the byte to the buffer and notify any waiters.
           buf[count++] = aByte;
       }

       public synchronized void newTextReady()
       {
           notifyAll();
       }

       /**
        * Reads the next byte of data from this input stream. The value
        * byte is returned as an <code>int</code> in the range
        * <code>0</code> to <code>255</code>. If no byte is available
        * because the end of the stream has been reached, the value
        * <code>-1</code> is returned.
        * <p>
        *
        * @return  the next byte of data, or <code>-1</code> if the end of
the
        *          stream has been reached.
        */
       public synchronized int read()
       {
           while (pos == count)
           {
               try
               {
                   wait();
               }
               catch (InterruptedException e)
               {
               }
           }
           return super.read();
       }

       /**
        * Reads up to <code>len</code> bytes of data into an array of bytes
        * from this input stream.
        * If <code>pos</code> equals <code>count</code>,
        * then the method blocks until data is avaialble.
        * Otherwise, the  number <code>k</code>
        * of bytes read is equal to the smaller of
        * <code>len</code> and <code>count-pos</code>.
        * If <code>k</code> is positive, then bytes
        * <code>buf[pos]</code> through <code>buf[pos+k-1]</code>
        * are copied into <code>b[off]</code>  through
        * <code>b[off+k-1]</code> in the manner performed
        * by <code>System.arraycopy</code>. The
        * value <code>k</code> is added into <code>pos</code>
        * and <code>k</code> is returned.
        * <p>
        *
        * @param   b     the buffer into which the data is read.
        * @param   off   the start offset of the data.
        * @param   len   the maximum number of bytes read.
        * @return  the total number of bytes read into the buffer, or
        *          <code>-1</code> if there is no more data because the end
of
        *          the stream has been reached.
        */
       public synchronized int read(byte b[], int off, int len)
       {
           while (pos == count)
           {
               try
               {
                   wait();
               }
               catch (InterruptedException e)
               {
               }
           }
           return super.read(b, off, len);
       }

   }

   private class FilteredStream extends FilterOutputStream
   {
       public FilteredStream(OutputStream aStream)
       {
           super(aStream);
       }

       private void commonWrite(String str)
       {
           if (EventQueue.isDispatchThread())
           {
               appendNewText(str);
           }
           else
           {
               SwingUtilities.invokeLater(new TextAreaAppender(str));
               if (textArea.isShowing())
               {
                   try
                   {
                       synchronized (textArea)
                       {
                           textArea.wait(100);
                       }
                   }
                   catch (InterruptedException e)
                   {
                   }
               }
           }
       }

       public void write(byte b[]) throws IOException
       {
           String aString = new String(b);
           commonWrite(aString);

       }

       public void write(byte b[], int off, int len) throws IOException
       {
           String aString = new String(b, off, len);
           commonWrite(aString);
       }

   }

   private class TextAreaAppender implements Runnable
   {
       String str;

       public TextAreaAppender(String str)
       {
           this.str = str;
       }

       public void run()
       {
           appendNewText(str);

       }
   }

}

Signature

Bill Tschumy
Otherwise -- Austin, TX
http://www.otherwise.com

Rob McDonald - 08 Jul 2005 13:30 GMT
Thanks, I'll take a close look at that.

Last night, I came across this...

http://javaalmanac.com/egs/javax.swing.text/ta_Console.html

You would think there would be a straightforward Swing component that would
set all this up for you.  Oh well...

Thanks again,

           Rob

> I've done this and it was somewhat tricky to get it right.  I've tried to
> extract the relevant code in the class below.  Hopefully I didn't cut out
[quoted text clipped - 49 lines]
>         setViewportView(textArea);
>         textArea.setLineWrap(true);

setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
>     }
>
[quoted text clipped - 261 lines]
>
> }
Andrew Thompson - 08 Jul 2005 13:32 GMT
> Thanks, I'll take a close look at that.

Can you take a close look at trimming the (now redundant)
350+ lines of the earlier post before *replying* in future?

Signature

Andrew Thompson
http://www.PhySci.org/codes/  Web & IT Help
http://www.PhySci.org/  Open-source software suite
http://www.1point1C.org/  Science & Technology
http://www.LensEscapes.com/  Images that escape the mundane

jan V - 25 Jul 2005 10:45 GMT
> Is there an easy way to set up a streaming swing console?  (Scrollbars &
> read-only clipboard access would be nice.)

Isn't their a component that does that in the Swing demo which comes with
every JDK? You could look at the demo's source.


Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.