As a useful example, I’m going to show a subclass of
java.awt.TextArea
that can be connected to an
output stream. As data is written onto the stream, it is appended to
the text area in the default character set (generally ISO Latin-1).
(This isn’t ideal. Since text areas contain text, a writer
would be a better source for this data; in later chapters I’ll
expand on this class to use a writer instead. For now this makes a
neat example.) This subclass is shown in Example 2.4.
The actual output stream is contained in an inner class inside the
StreamedTextArea
class. Each
StreamedTextArea
component contains a
TextAreaOutputStream
object in its
theOutput
field. Client programmers access this
object via the getOutputStream()
method of the
StreamedTextArea
class. The
StreamedTextArea
class has five overloaded
constructors that imitate the five constructors in the
java.awt.TextArea
class, each taking a different
combination of text, rows, columns, and scrollbar information. The
first four constructors merely pass their arguments and suitable
defaults to the most general fifth constructor using
this()
. The fifth constructor calls the most
general superclass constructor, then calls
setEditable(false)
to ensure that the user
doesn’t change the text while output is streaming into it.
I’ve chosen not to override any methods in the
TextArea
superclass. However, you might want to do
so if you feel a need to change the normal abilities of a text area.
For example, you could include a do-nothing
append()
method so that data can only be moved
into the text area via the provided output stream or a
setEditable()
method that doesn’t allow the
client programmer to make this area editable.
Example 2-4. The StreamedTextArea Component
package com.macfaq.awt; import java.awt.*; import java.io.*; public class StreamedTextArea extends TextArea { OutputStream theOutput = new TextAreaOutputStream(); public StreamedTextArea() { this("", 0, 0, SCROLLBARS_BOTH); } public StreamedTextArea(String text) { this(text, 0, 0, SCROLLBARS_BOTH); } public StreamedTextArea(int rows, int columns) { this("", rows, columns, SCROLLBARS_BOTH); } public StreamedTextArea(String text, int rows, int columns) { this(text, rows, columns, SCROLLBARS_BOTH); } public StreamedTextArea(String text, int rows, int columns, int scrollbars) { super(text, rows, columns, scrollbars); setEditable(false); } public OutputStream getOutputStream() { return theOutput; } class TextAreaOutputStream extends OutputStream { public synchronized void write(int b) { // recall that the int should really just be a byte b &= 0x000000FF; // must convert byte to a char in order to append it char c = (char) b; append(String.valueOf(c)); } public synchronized void write(byte[] data, int offset, int length) { append(new String(data, offset, length)); } } }
The TextAreaOutputStream
inner class is quite
simple. It extends OutputStream
and thus must
implement the abstract method write()
. It also
overrides the primary array write()
method to
provide a more efficient implementation. To use this class, you
simply add an instance of it to a container like an applet or a
window, much as you’d add a regular text area. Next you invoke
its getOutputStream()
method to get a reference to
the output stream for the area, then use the usual
write()
methods to write into the text area. Often
these steps will take place at different times in different methods.
Figure 2.1 shows a program using a
StreamedTextArea
to display data downloaded from
http://www.oreilly.com/. The
application in this picture will be developed in Chapter 5.
I’ll revisit and improve this class in future chapters using techniques you haven’t learned yet. In particular, I’ll pay much more attention to the issue of character sets and encodings.
3.143.4.181