Received: from SOUTH-STATION-ANNEX.MIT.EDU by po10.MIT.EDU (5.61/4.7) id AA19163; Mon, 29 Nov 99 13:39:17 EST
Received: from hermes.javasoft.com by MIT.EDU with SMTP
	id AA23664; Mon, 29 Nov 99 13:38:25 EST
Received: (from nobody@localhost)
	by hermes.java.sun.com (8.9.3+Sun/8.9.1) id SAA09831;
	Mon, 29 Nov 1999 18:38:24 GMT
Date: Mon, 29 Nov 1999 18:38:24 GMT
Message-Id: <199911291838.SAA09831@hermes.java.sun.com>
X-Authentication-Warning: hermes.java.sun.com: Processed from queue /bulkmail/data/ed_91/mqueue4
X-Mailing: 193
From: JDCTechTips@sun.com
Subject: JDC Tech Tips  November 24, 1999
To: JDCMember@sun.com
Reply-To: JDCTechTips@sun.com
Errors-To: bounced_mail@hermes.java.sun.com
Precedence: junk
Mime-Version: 1.0
Content-Type: text/plain; charset=us-ascii
X-Mailer: Beyond Email 2.2


 J  D  C    T  E  C  H    T  I  P  S

                      TIPS, TECHNIQUES, AND SAMPLE CODE


WELCOME to the Java Developer Connection(sm) (JDC) Tech Tips, 
November 24, 1999. This issue covers:

         * Color Choosers
         * Loading Text Files in Swing Efficiently

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 

COLOR CHOOSERS

JColorChooser is a Swing class that you use to select a color. 
It typically pops up a window with a color chooser dialog in it.
You choose a color (like blue or red), and the window goes away. 
The result of this process is an instance of the java.awt.Color
class. A good context for JColorChooser is a word processor, 
where you're specifying the color to use for highlighted text.

You have three ways of selecting or entering a color with 
JColorChooser. You can choose a color swatch, a small square of 
a particular color. There's also RGB (red/green/blue) and HSB
(hue/saturation/brightness) available; these represent a color 
using numerical values. For example, if you enter the values 
(255, 0, 255), you get the color magenta. You can also specify 
an initial color to a JColorChooser object.

JColorChooser is typically used as a pop-up modal dialog. However 
you can also use it as an always visible component; in this case, 
you are notified of color changes via event listeners. Here's an 
example of using JColorChooser in this latter way:

    import java.awt.*;
    import java.awt.event.*;
    import javax.swing.*;
    import javax.swing.colorchooser.*;
    import javax.swing.event.*;

    public class ColorChoose {
        public static void main(String args[]) {
            final JFrame frame = new JFrame("Color Chooser Demo");
            frame.addWindowListener(new WindowAdapter() {
                public void windowClosing(WindowEvent e) {
                    System.exit(0);
                }
            });

            // set up the canvas to draw on

            final Canvas canv = new Canvas();
            canv.setSize(new Dimension(300, 300));

            // set up the color chooser and its listener

            final JColorChooser jcc = new JColorChooser(Color.blue);
            final ColorSelectionModel csm = jcc.getSelectionModel();
            csm.addChangeListener(
                new ChangeListener() {
                    public void stateChanged(ChangeEvent e) {

                        // retrieve the current color and draw

                        Color c = csm.getSelectedColor();
                        Graphics g = canv.getGraphics();
                        g.setColor(c);
                        g.fillOval(150, 150, 100, 100);
                    }
                }
            );

            JPanel panel = new JPanel();
            panel.setLayout(new BorderLayout());
            panel.add("North", jcc);
            panel.add("South", canv);

            frame.getContentPane().add(panel);
            frame.pack();
            frame.setVisible(true);
        }
    }

The program sets up two regions. The upper region contains a color
chooser that is set to an initial color of blue. In the lower 
region, a Canvas object is used to draw graphical objects. 
Choose a color in the upper area, and the program displays
a filled oval of that color in the lower area.

Actual color changes in the JColorChooser are abstracted through
a ColorSelectionModel. This is an interface that supports methods
for getting and setting colors, and tracking color change. Notice
that the program adds a change listener to the model. The change 
listener tracks changes to the current color. When a color changes,
the change listener calls stateChanged to retrieve the color and 
draw a graphical object in the new color.

LOADING TEXT FILES IN SWING EFFICIENTLY

Suppose that you'd like to read a large text file into a Swing 
text area, using either a JTextArea or a JTextPane object. Are 
there any efficiency issues to consider in this operation?

To find out, you can set up a test program that uses
JTextComponent.read to read in a text file into a text area. Then 
experiment. Run the program specifying first a JTextArea and then
a JTextPane as the target for the text, and compare the program 
running times. Here's a program you can use to run the test:

    import java.awt.*;
    import java.awt.event.*;
    import javax.swing.*;
    import javax.swing.text.*;
    import java.io.*;

    public class ReadDemo {

        // read the file into the pane

        static void readin(String fn, JTextComponent pane) {
            try {
                FileReader fr = new FileReader(fn);
                pane.read(fr, null);
                fr.close();
            }
            catch (IOException e) {
                System.err.println(e);
            }
        }

        public static void main(String args[]) {
            final JFrame frame = new JFrame("Read Demo");
            frame.addWindowListener(new WindowAdapter() {
                public void windowClosing(WindowEvent e) {
                    System.exit(0);
                }
            });

            // set up the text pane, either a JTextArea or JTextPane

            final JTextComponent textpane = new JTextArea();
            //final JTextComponent textpane = new JTextPane();

            // set up a scroll pane for the text pane

            final JScrollPane pane = new JScrollPane(textpane);
            pane.setPreferredSize(new Dimension(600, 600));

            // set up the file chooser

            String cwd = System.getProperty("user.dir");
            final JFileChooser jfc = new JFileChooser(cwd);
            final JLabel elapsed = new JLabel("Elapsed time: ");

            JButton filebutton = new JButton("Choose File");
            filebutton.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent e) {
                    if (jfc.showOpenDialog(frame) !=
                        JFileChooser.APPROVE_OPTION)
                            return;
                    File f = jfc.getSelectedFile();

                    // record the current time and read the file

                    final long s_time = System.currentTimeMillis();
                    frame.setCursor(Cursor.getPredefinedCursor(
                        Cursor.WAIT_CURSOR));
                    readin(f.toString(), textpane);

                    // wait for read to complete and update time

                    SwingUtilities.invokeLater(new Runnable() {
                        public void run() {
                            frame.setCursor(Cursor.
                                getPredefinedCursor(
                                Cursor.DEFAULT_CURSOR));
                            long t = System.currentTimeMillis() -
                                   s_time;
                            elapsed.setText("Elapsed time: " + t);
                        }
                    });
                }
            });

            JPanel buttonpanel = new JPanel();
            buttonpanel.add(filebutton);
            buttonpanel.add(elapsed);

            JPanel panel = new JPanel();
            panel.setLayout(new BorderLayout());
            panel.add("North", buttonpanel);
            panel.add("Center", pane);

            frame.getContentPane().add(panel);
            frame.pack();
            frame.setVisible(true);
        }
    }

The program displays a Choose File button. Click on the button, 
and a file chooser dialog appears. You can then select a text 
file to read into the text area. Depending on which of these two 
lines is uncommented:

    final JTextComponent textpane = new JTextArea();
    //final JTextComponent textpane = new JTextPane();

the text will be read into a JTextArea or into a JTextPane. 
JTextArea supports plain text (similar to the old AWT TextArea 
class), while JTextPane handles text with attributes (such as 
underlining or italics).

The program records the time just before reading the file. 
Then it records the time after the file is read. The elapsed time
is the difference between the two times. Notice how 
SwingUtilities.invokeLater is used to display the elapsed time.
It is necessary because the read method is asynchronous, that is, 
the read operation is not complete when the method returns. Display 
updating may noticeably lag behind, because updating is done via 
events placed on the event queue, and the program calls read from 
the event dispatch thread. 

  You can demonstrate the display lag by compiling and 
  running the program after commenting out a number of
  lines:

  //    SwingUtilities.invokeLater(new Runnable() {
  //        public void run() {
              frame.setCursor(Cursor.
                  getPredefinedCursor(
                  Cursor.DEFAULT_CURSOR));
              long t = System.currentTimeMillis() -
                     s_time;
              elapsed.setText("Elapsed time: " + t);
  //         }
  //   });

  You will see that the wrong elapsed time is posted when you
  make this change. The time is calculated after read returns.
  Unfortunately, this calculation fails to account for the fact 
  that the file is still being processed for display purposes.  
  The larger the file, the more inaccurate the elapsed time 
  calculation. This problem is most pronounced when you read 
  into a JTextPane.
 
Getting back to the example program... so, there will be update 
events to process after actionPerformed returns. To deal with this 
issue, for timing purposes, SwingUtilities.invokeLater is called 
to queue a runnable task. The runnable task displays the elapsed 
time once the read/display operation is complete. The task runs 
after all the events ahead of it in the queue have been processed.

When you run the test you will see that text can be read into a
JTextArea 3-4 times faster than into a JTextPane. To make sure 
that the comparison is fair, you need to ensure that the file 
you are reading is either cached or uncached in both cases, that is, 
that both file reads are directly from disk, or else directly from 
the operating system cache.

The "bottom line" is that JTextPane does more for you than JTextArea,
but at higher cost. If you're simply interested in reading plain
text, there may be no point in paying that cost.




.  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .

- NOTE
The names on the JDC mailing list are used for internal Sun
Microsystems(tm) purposes only.  To remove your name from the list,
see Subscribe/Unsubscribe below.


- FEEDBACK
Comments?  Send your feedback on the JDC Tech Tips to:

jdc-webmaster@java.sun.com


- SUBSCRIBE/UNSUBSCRIBE
The JDC Tech Tips are sent to you because you elected to subscribe
when you registered as a JDC member.  To unsubscribe from JDC Email,
go to the following address and enter the email address you wish to
remove from the mailing list:

http://developer.java.sun.com/unsubscribe.html


To become a JDC member and subscribe to this newsletter go to:

http://java.sun.com/jdc/


- ARCHIVES
You'll find the JDC Tech Tips archives at:

http://developer.java.sun.com/developer/TechTips/index.html


- COPYRIGHT
Copyright 1999 Sun Microsystems, Inc. All rights reserved.
901 San Antonio Road, Palo Alto, California 94303 USA.

This document is protected by copyright.  For more information, see:

http://developer.java.sun.com/developer/copyright.html


This issue of the JDC Tech Tips is written by Glen McCluskey.

JDC Tech Tips 
November 24, 1999












