User interfaces for object-oriented systems, Part 5: Useful stuff

Build an application that puts user-interface principles into practice

1 2 3 4 5 Page 5
Page 5 of 5
List 9. /src/com/holub/ui/Scrollable_JTextArea.java
   1: package com.holub.ui;
   2: 
   3: import javax.swing.*;
   4: import java.awt.*;
   5: import java.awt.event.*;
   6: 
   7: /**
   8:  *  A convenience class that creates a JTextArea and wraps it into
   9:  *  a JScrollPane for you. A Scrollable_JTextArea is a JScrollPane
  10:  *  that contains a JTextArea.
  11:  */
  12: 
  13: public class Scrollable_JTextArea extends JScrollPane
  14: {
  15:     /******************************************************************
  16:      *  Create an empty Scrollable_JTextArea with scroll bars created as
  17:      *  needed, and word-wrapping on in the encapsulate JTextArea. (The
  18:      *  latter  means that you won't ever get a horizontal scroll bar.
  19:      *  You can change this behavior by sending a setLineWrap(false)
  20:      *  message to the Scrollable_JTextArea object.) The default preferred
  21:      *  size is 250 x 250.
  22:      */
  23: 
  24:   private final JTextArea text = new JTextArea();
  25: 
  26:   public Scrollable_JTextArea( boolean write_only )
  27:     {
  28:         // Set up for line wrap and a vertical scroll bar. Other
  29:         // alternatives could be horizontal and vertical
  30:         // scroll bars and no line wrap.
  31: 
  32:         text.setLineWrap(true);
  33:         text.setWrapStyleWord(true);
  34: 
  35:         setViewportView( text );
  36: 
  37:         setPreferredSize( new Dimension(250, 250) );
  38:         setSize         ( new Dimension(250, 250) );
  39:         setBorder       ( BorderFactory.createEtchedBorder() );
  40: 
  41:         if( write_only )
  42:         {
  43:             text.setEditable  ( false );
  44:             text.addFocusListener
  45:             (   new FocusAdapter()
  46:               {   public void focusGained(FocusEvent e)
  47:                     {   Scrollable_JTextArea.this.requestFocus();
  48:                     }
  49:                 }
  50:             );
  51:         }
  52:     }
  53: 
  54:     /******************************************************************
  55:      * Convenience method, sets the initial text to initial_text.
  56:      */
  57:   public Scrollable_JTextArea( String initial_text, boolean write_only )
  58:     {   this(write_only);
  59:         text.setText( initial_text );
  60:     }
  61: 
  62:     /******************************************************************
  63:      * Convenience method, sets the initial text to initial_text, one
  64:      * String per line. The initial font is 12-point Monospaced.
  65:      * The size is controlled by the size of the text. The number of
  66:      * columns is the maximum number of characters on a line in
  67:      * initial-text; the number of rows is the number of lines.
  68:      * Word wrapping is off.
  69:      */
  70: 
  71:   public Scrollable_JTextArea( String[] initial_text, boolean write_only )
  72:     {   this(write_only);
  73:         text.setLineWrap( false                                  );
  74:         text.setFont    ( new Font("Monospaced", Font.PLAIN, 12) );
  75:         text.setRows    ( initial_text.length                    );
  76: 
  77:         int width  = 0;
  78:         for( int i = 0 ; i < initial_text.length; ++i )
  79:         {   String current = initial_text[i];
  80:             width = Math.max( width, current.length() );
  81:             text.append( current + "\n" );
  82:         }
  83: 
  84:         text.setColumns( width );
  85: 
  86:         Dimension size = text.getPreferredSize();
  87:         size.height += 5;   // Add some slop so that scroll bars won't
  88:         size.width  += 5;   // be displayed initially.
  89: 
  90:         setPreferredSize( size );
  91:         setSize         ( size );
  92:     }
  93: 
  94:     /******************************************************************
  95:      * Convenience methods, just chain through to the
  96:      * setText() method of the contained JTextArea();
  97:      */
  98: 
  99:   public final void setText( String str )
 100:     {   text.setText( str );
 101:     }
 102: 
 103:   public final void append( String str )
 104:     {   text.append( str );
 105:     }
 106: 
 107:   public final void setEditable(boolean on)
 108:     {   text.setEditable(on); 
 109:     }
 110: 
 111:   public final void setLineWrap(boolean on)
 112:     {   text.setLineWrap(on);
 113:     }
 114: 
 115:   public final String getText()
 116:     {   return text.getText();
 117:     }
 118: 
 119:   public final void setBackground(Color c)
 120:     {  if(text!=null) text.setBackground(c);
 121:     }
 122: 
 123:   public final void setForeground(Color c)
 124:     { if(text!=null) text.setForeground(c);
 125:     }
 126: 
 127:   public final void setFont(Font f)
 128:     { if(text!=null) text.setFont(f);
 129:     }
 130: 
 131:     /******************************************************************
 132:      * Accessor method, provides access to the contained JTextArea
 133:      * if you need it.
 134:      */
 135:   public final JTextArea getTextArea( ){ return text; }
 136: 
 137:     /******************************************************************
 138:      * Container of the unit-test
 139:      */
 140:   static public class Test
 141:     {
 142:       static public void main( String[] args )
 143:         {   test1();
 144:             test2();
 145:         }
 146: 
 147:         static void test1()
 148:         {
 149:             Scrollable_JTextArea text = new Scrollable_JTextArea(
 150:                     "This is an editable JTextArea " +
 151:                     "that has been initialized with the setText method. " +
 152:                     "A text area is a \"plain\" text component, " +
 153:                     "which means that although it can display text " +
 154:                     "in any font, all of the text is in the same font.",
 155:                     false
 156:             );
 157: 
 158:             JFrame frame = new JFrame();
 159:             frame.getContentPane().add( text );
 160:             frame.setVisible( true );
 161: 
 162:             try{ Thread.currentThread().sleep(10000); } catch (Exception e){}
 163: 
 164:             text.setText(   "Here is a completely new\n"+
 165:                             "chunk of text\n"+
 166:                             "this time\n" +
 167:                             "with newlines."
 168:                         );
 169:         }
 170: 
 171:         static void test2()
 172:         {   String[] contents = { "This is a read-only ->",
 173:                                   "multiline text control ->",
 174:                                   "that should display->",
 175:                                   "four lines.->"
 176:                                 };
 177: 
 178:             Scrollable_JTextArea text = new Scrollable_JTextArea( contents,true );
 179:             JFrame frame = new JFrame();
 180:             frame.getContentPane().add( text );
 181:             frame.pack();
 182:             frame.setVisible( true );
 183:         }
 184:     }
 185: }
         

Loose ends

The following classes were covered in depth in previous articles, but they're used either in the foregoing code or by the calculator itself, so I've reprinted them here for the sake of completeness.

List 10. /src/com/holub/asynch/JDK_11_unloading_bug_fix.java
   1: package com.holub.asynch;
   2: 
   3: /**
   4:  * <table border=1 cellspacing=0 cellpadding=5><tr><td><font size=-1>  5:  * <center>(c) 1999, Allen I. Holub.</center>
   6:  * <p>
   7:  * This code may not be distributed by yourself except in binary form,
   8:  * incorporated into a java .class file. You may use this code freely
   9:  * for personal purposes, but you may not incorporate it into any
  10:  * commercial product without express permission of Allen I. Holub in
  11:  * writing.
  12:  * </td></tr></table>
  13:  *
  14:  *  <p>
  15:  *  This class provides a workaround for a bug in the JDK 1.1 VM that
  16:  *  unloads classes too aggressively. The problem is that if the only
  17:  *  reference to an object is held in a static member of the object, the
  18:  *  class is subject to unloading and the static member will be discarded.
  19:  *  This behavior causes a lot of grief when you're implementing a
  20:  *  Singleton. Use it like this:
  21:  *
  22:  *  
  23:  *  class Singleton
  24:  *  {   private Singleton()
  25:  *      {   new JDK_11_unloading_bug_fix(Singleton.class);
  26:  *      }
  27:  *      // ...
  28:  *  }
  29:  *  
  30:  *  In either event, once the "JDK_11_unloading_bug_fix" object is
  31:  *  created, the class (and its static fields) won't be unloaded for
  32:  *  the life of the program.
  33:  */
  34: 
  35: public class JDK_11_unloading_bug_fix
  36: { 
  37:   public JDK_11_unloading_bug_fix( final Class the_class )
  38:     {   
  39:         if( System.getProperty("java.version").startsWith("1.1") )
  40:         {
  41:             Thread t =
  42:                 new Thread()
  43:               {   private Class singleton_class = the_class;
  44:                   public void run()
  45:                     {   synchronized(this)
  46:                         {   try{ wait(); }catch(InterruptedException e){}
  47:                         }
  48:                     }
  49:                 };
  50: 
  51:             // I'm not exactly sure why synchronization is necessary, below,
  52:             // but without it, some VMs complain of an illegal-monitor
  53:             // state. The effect is to stop the wait() from executing
  54:             // until the thread is fully started.
  55: 
  56:             synchronized( t )
  57:             {   t.setDaemon(true);  // so program can shut down
  58:                 t.start();
  59:             }
  60:         }
  61:     }
  62: }
         
List 11. /src/com/holub/ui/AncestorAdapter.java
   1: package com.holub.ui;
   2: 
   3: import javax.swing.event.*;
   4: 
   5: /** Corrects a flaw in Swing, provides an AncestorListener
   6:  *  implementation made up of empty methods.
   7:  */
   8: 
   9: public class AncestorAdapter implements AncestorListener
  10: {   public void ancestorAdded   ( AncestorEvent event ){}
  11:   public void ancestorMoved   ( AncestorEvent event ){}
  12:   public void ancestorRemoved ( AncestorEvent event ){}
  13: }
         
Allen Holub runs Holub Associates in the San Francisco Bay Area. The firm designs software and guides you through its implementation in much the same way that traditional architects design buildings and help contractors construct them. Holub Associates also provides training in object-oriented design and Java, provides design-review and mentoring services, and does occasional Java implementations. Allen has been working in the computer industry since 1979. He is widely published in magazines (Dr. Dobb's Journal, Programmers Journal, Byte, and MSJ, among others). He is working on his eighth book, which will present the complete sources for a Java compiler written in Java. A former C++ programmer, Allen abandoned it for Java in early 1996. He now looks at C++ as a bad dream, the memory of which is mercifully fading. He has built two operating systems from scratch, several compilers, and various application programs ranging in scope from robotics controllers to children's software. He has been teaching programming, both on his own and for the University of California Berkeley Extension, since 1982. Get information and contact Allen via his Website http://www.holub.com.

Learn more about this topic

The complete Java Toolbox archive

1 2 3 4 5 Page 5
Page 5 of 5