You are previewing Learning Java, 4th Edition.

Learning Java, 4th Edition

Cover of Learning Java, 4th Edition by Daniel Leuck... Published by O'Reilly Media, Inc.
  1. Learning Java
  2. Preface
    1. Who Should Read This Book
    2. New Developments
      1. New in This Edition (Java 6 and 7)
    3. Using This Book
    4. Online Resources
    5. Conventions Used in This Book
    6. Using Code Examples
    7. Safari® Books Online
    8. How to Contact Us
    9. Acknowledgments
  3. 1. A Modern Language
    1. Enter Java
      1. Java’s Origins
      2. Growing Up
    2. A Virtual Machine
    3. Java Compared with Other Languages
    4. Safety of Design
      1. Simplify, Simplify, Simplify...
      2. Type Safety and Method Binding
      3. Incremental Development
      4. Dynamic Memory Management
      5. Error Handling
      6. Threads
      7. Scalability
    5. Safety of Implementation
      1. The Verifier
      2. Class Loaders
      3. Security Managers
    6. Application and User-Level Security
    7. A Java Road Map
      1. The Past: Java 1.0–Java 1.6
      2. The Present: Java 7
      3. The Future
      4. Availability
  4. 2. A First Application
    1. Java Tools and Environment
    2. Configuring Eclipse and Creating a Project
      1. Importing the Learning Java Examples
    3. HelloJava
      1. Classes
      2. The main() Method
      3. Classes and Objects
      4. Variables and Class Types
      5. HelloComponent
      6. Inheritance
      7. The JComponent Class
      8. Relationships and Finger Pointing
      9. Package and Imports
      10. The paintComponent() Method
    4. HelloJava2: The Sequel
      1. Instance Variables
      2. Constructors
      3. Events
      4. The repaint() Method
      5. Interfaces
    5. HelloJava3: The Button Strikes!
      1. Method Overloading
      2. Components
      3. Containers
      4. Layout
      5. Subclassing and Subtypes
      6. More Events and Interfaces
      7. Color Commentary
      8. Static Members
      9. Arrays
      10. Our Color Methods
    6. HelloJava4: Netscape’s Revenge
      1. Threads
      2. The Thread Class
      3. The Runnable Interface
      4. Starting the Thread
      5. Running Code in the Thread
      6. Exceptions
      7. Synchronization
  5. 3. Tools of the Trade
    1. JDK Environment
    2. The Java VM
    3. Running Java Applications
      1. System Properties
    4. The Classpath
      1. javap
    5. The Java Compiler
    6. JAR Files
      1. File Compression
      2. The jar Utility
      3. The pack200 Utility
    7. Policy Files
      1. The Default Security Manager
      2. The policytool Utility
      3. Using a Policy File with the Default Security Manager
  6. 4. The Java Language
    1. Text Encoding
    2. Comments
      1. Javadoc Comments
    3. Types
      1. Primitive Types
      2. Reference Types
      3. A Word About Strings
    4. Statements and Expressions
      1. Statements
      2. Expressions
    5. Exceptions
      1. Exceptions and Error Classes
      2. Exception Handling
      3. Bubbling Up
      4. Stack Traces
      5. Checked and Unchecked Exceptions
      6. Throwing Exceptions
      7. try Creep
      8. The finally Clause
      9. Try with Resources
      10. Performance Issues
    6. Assertions
      1. Enabling and Disabling Assertions
      2. Using Assertions
    7. Arrays
      1. Array Types
      2. Array Creation and Initialization
      3. Using Arrays
      4. Anonymous Arrays
      5. Multidimensional Arrays
      6. Inside Arrays
  7. 5. Objects in Java
    1. Classes
      1. Accessing Fields and Methods
      2. Static Members
    2. Methods
      1. Local Variables
      2. Shadowing
      3. Static Methods
      4. Initializing Local Variables
      5. Argument Passing and References
      6. Wrappers for Primitive Types
      7. Autoboxing and Unboxing of Primitives
      8. Variable-Length Argument Lists
      9. Method Overloading
    3. Object Creation
      1. Constructors
      2. Working with Overloaded Constructors
      3. Static and Nonstatic Initializer Blocks
    4. Object Destruction
      1. Garbage Collection
      2. Finalization
      3. Weak and Soft References
    5. Enumerations
      1. Enum Values
      2. Customizing Enumerations
  8. 6. Relationships Among Classes
    1. Subclassing and Inheritance
      1. Shadowed Variables
      2. Overriding Methods
      3. Special References: this and super
      4. Casting
      5. Using Superclass Constructors
      6. Full Disclosure: Constructors and Initialization
      7. Abstract Methods and Classes
    2. Interfaces
      1. Interfaces as Callbacks
      2. Interface Variables
      3. Subinterfaces
    3. Packages and Compilation Units
      1. Compilation Units
      2. Package Names
      3. Class Visibility
      4. Importing Classes
    4. Visibility of Variables and Methods
      1. Basic Access Modifiers
      2. Subclasses and Visibility
      3. Interfaces and Visibility
    5. Arrays and the Class Hierarchy
      1. ArrayStoreException
    6. Inner Classes
      1. Inner Classes as Adapters
      2. Inner Classes Within Methods
  9. 7. Working with Objects and Classes
    1. The Object Class
      1. Equality and Equivalence
      2. Hashcodes
      3. Cloning Objects
    2. The Class Class
    3. Reflection
      1. Modifiers and Security
      2. Accessing Fields
      3. Accessing Methods
      4. Accessing Constructors
      5. What About Arrays?
      6. Accessing Generic Type Information
      7. Accessing Annotation Data
      8. Dynamic Interface Adapters
      9. What Is Reflection Good For?
    4. Annotations
      1. Using Annotations
      2. Standard Annotations
      3. The apt Tool
  10. 8. Generics
    1. Containers: Building a Better Mousetrap
      1. Can Containers Be Fixed?
    2. Enter Generics
      1. Talking About Types
    3. “There Is No Spoon”
      1. Erasure
      2. Raw Types
    4. Parameterized Type Relationships
      1. Why Isn’t a List<Date> a List<Object>?
    5. Casts
    6. Writing Generic Classes
      1. The Type Variable
      2. Subclassing Generics
      3. Exceptions and Generics
      4. Parameter Type Limitations
    7. Bounds
      1. Erasure and Bounds (Working with Legacy Code)
    8. Wildcards
      1. A Supertype of All Instantiations
      2. Bounded Wildcards
      3. Thinking Outside the Container
      4. Lower Bounds
      5. Reading, Writing, and Arithmetic
      6. <?>, <Object>, and the Raw Type
      7. Wildcard Type Relationships
    9. Generic Methods
      1. Generic Methods Introduced
      2. Type Inference from Arguments
      3. Type Inference from Assignment Context
      4. Explicit Type Invocation
      5. Wildcard Capture
      6. Wildcard Types Versus Generic Methods
    10. Arrays of Parameterized Types
      1. Using Array Types
      2. What Good Are Arrays of Generic Types?
      3. Wildcards in Array Types
    11. Case Study: The Enum Class
    12. Case Study: The sort() Method
    13. Conclusion
  11. 9. Threads
    1. Introducing Threads
      1. The Thread Class and the Runnable Interface
      2. Controlling Threads
      3. Death of a Thread
    2. Threading an Applet
      1. Issues Lurking
    3. Synchronization
      1. Serializing Access to Methods
      2. Accessing class and instance Variables from Multiple Threads
      3. The wait() and notify() Methods
      4. Passing Messages
      5. ThreadLocal Objects
    4. Scheduling and Priority
      1. Thread State
      2. Time-Slicing
      3. Priorities
      4. Yielding
    5. Thread Groups
      1. Working with ThreadGroups
      2. Uncaught Exceptions
    6. Thread Performance
      1. The Cost of Synchronization
      2. Thread Resource Consumption
    7. Concurrency Utilities
      1. Executors
      2. Locks
      3. Synchronization Constructs
      4. Atomic Operations
    8. Conclusion
  12. 10. Working with Text
    1. Text-Related APIs
    2. Strings
      1. Constructing Strings
      2. Strings from Things
      3. Comparing Strings
      4. Searching
      5. Editing
      6. String Method Summary
      7. StringBuilder and StringBuffer
    3. Internationalization
      1. The java.util.Locale Class
      2. Resource Bundles
    4. Parsing and Formatting Text
      1. Parsing Primitive Numbers
      2. Tokenizing Text
    5. Printf-Style Formatting
      1. Formatter
      2. The Format String
      3. String Conversions
      4. Primitive and Numeric Conversions
      5. Flags
      6. Miscellaneous
    6. Formatting with the java.text Package
      1. MessageFormat
    7. Regular Expressions
      1. Regex Notation
      2. The java.util.regex API
  13. 11. Core Utilities
    1. Math Utilities
      1. The java.lang.Math Class
      2. Big/Precise Numbers
      3. Floating-Point Components
      4. Random Numbers
    2. Dates and Times
      1. Working with Calendars
      2. Time Zones
      3. Parsing and Formatting with DateFormat
      4. Printf-Style Date and Time Formatting
    3. Timers
    4. Collections
      1. The Collection Interface
      2. Iterator
      3. Collection Types
      4. The Map Interface
      5. Collection Implementations
      6. Hash Codes and Key Values
      7. Synchronized and Unsynchronized Collections
      8. Read-Only and Read-Mostly Collections
      9. WeakHashMap
      10. EnumSet and EnumMap
      11. Sorting Collections
      12. A Thrilling Example
    5. Properties
      1. Loading and Storing
      2. System Properties
    6. The Preferences API
      1. Preferences for Classes
      2. Preferences Storage
      3. Change Notification
    7. The Logging API
      1. Overview
      2. Logging Levels
      3. A Simple Example
      4. Logging Setup Properties
      5. The Logger
      6. Performance
    8. Observers and Observables
  14. 12. Input/Output Facilities
    1. Streams
      1. Basic I/O
      2. Character Streams
      3. Stream Wrappers
      4. Pipes
      5. Streams from Strings and Back
      6. Implementing a Filter Stream
    2. File I/O
      1. The java.io.File Class
      2. File Streams
      3. RandomAccessFile
      4. Resource Paths
    3. The NIO File API
      1. FileSystem and Path
      2. NIO File Operations
      3. Directory Operations
      4. Watching Paths
    4. Serialization
      1. Initialization with readObject()
      2. SerialVersionUID
    5. Data Compression
      1. Archives and Compressed Data
      2. Decompressing Data
      3. Zip Archive As a Filesystem
    6. The NIO Package
      1. Asynchronous I/O
      2. Performance
      3. Mapped and Locked Files
      4. Channels
      5. Buffers
      6. Character Encoders and Decoders
      7. FileChannel
      8. Scalable I/O with NIO
  15. 13. Network Programming
    1. Sockets
      1. Clients and Servers
      2. author="pat” timestamp="20120926T110720-0500” comment="one of those sections I hate to get rid of but is less relevant in terms of the example... should probably find a more modern example...”The DateAtHost Client
      3. The TinyHttpd Server
      4. Socket Options
      5. Proxies and Firewalls
    2. Datagram Sockets
      1. author="pat” timestamp="20120926T141346-0500” comment="I actually rewrote this as a standalone client but then decided to leave it as an applet”The HeartBeat Applet
      2. InetAddress
    3. Simple Serialized Object Protocols
      1. A Simple Object-Based Server
    4. Remote Method Invocation
      1. Real-World Usage
      2. Remote and Nonremote Objects
      3. An RMI Example
      4. RMI and CORBA
    5. Scalable I/O with NIO
      1. Selectable Channels
      2. Using Select
      3. LargerHttpd
      4. Nonblocking Client-Side Operations
  16. 14. Programming for the Web
    1. Uniform Resource Locators (URLs)
    2. The URL Class
      1. Stream Data
      2. Getting the Content as an Object
      3. Managing Connections
      4. Handlers in Practice
      5. Useful Handler Frameworks
    3. Talking to Web Applications
      1. Using the GET Method
      2. Using the POST Method
      3. The HttpURLConnection
      4. SSL and Secure Web Communications
      5. URLs, URNs, and URIs
    4. Web Services
      1. XML-RPC
      2. WSDL
      3. The Tools
      4. The Weather Service Client
  17. 15. Web Applications and Web Services
    1. Web Application Technologies
      1. Page-Oriented Versus “Single Page” Applications
      2. JSPs
      3. XML and XSL
      4. Web Application Frameworks
      5. Google Web Toolkit
      6. HTML5, AJAX, and More...
    2. Java Web Applications
      1. The Servlet Lifecycle
      2. Servlets
      3. The HelloClient Servlet
      4. The Servlet Response
      5. Servlet Parameters
      6. The ShowParameters Servlet
      7. User Session Management
      8. The ShowSession Servlet
      9. The ShoppingCart Servlet
      10. Cookies
      11. The ServletContext API
      12. Asynchronous Servlets
    3. WAR Files and Deployment
      1. Configuration with web.xml and Annotations
      2. URL Pattern Mappings
      3. Deploying HelloClient
      4. Error and Index Pages
      5. Security and Authentication
      6. Protecting Resources with Roles
      7. Secure Data Transport
      8. Authenticating Users
      9. Procedural Authorization
    4. Servlet Filters
      1. A Simple Filter
      2. A Test Servlet
      3. Declaring and Mapping Filters
      4. Filtering the Servlet Request
      5. Filtering the Servlet Response
    5. Building WAR Files with Ant
      1. A Development-Oriented Directory Layout
      2. Deploying and Redeploying WARs with Ant
    6. Implementing Web Services
      1. Defining the Service
      2. Our Echo Service
      3. Using the Service
      4. Data Types
    7. Conclusion
  18. 16. Swing
    1. Components
      1. Peers and Look-and-Feel
      2. The MVC Framework
      3. Painting
      4. Enabling and Disabling Components
      5. Focus, Please
      6. Other Component Methods
      7. Layout Managers
      8. Insets
      9. Z-Ordering (Stacking Components)
      10. The revalidate() and doLayout() Methods
      11. Managing Components
      12. Listening for Components
      13. Windows, Frames and Splash Screens
      14. Other Methods for Controlling Frames
      15. Content Panes
      16. Desktop Integration
    2. Events
      1. Event Receivers and Listener Interfaces
      2. Event Sources
      3. Event Delivery
      4. Event Types
      5. The java.awt.event.InputEvent Class
      6. Mouse and Key Modifiers on InputEvents
      7. Focus Events
    3. Event Summary
      1. Adapter Classes
      2. Dummy Adapters
    4. The AWT Robot!
    5. Multithreading in Swing
  19. 17. Using Swing Components
    1. Buttons and Labels
      1. HTML Text in Buttons and Labels
    2. Checkboxes and Radio Buttons
    3. Lists and Combo Boxes
    4. The Spinner
    5. Borders
    6. Menus
    7. Pop-Up Menus
      1. Component-Managed Pop Ups
    8. The JScrollPane Class
    9. The JSplitPane Class
    10. The JTabbedPane Class
    11. Scrollbars and Sliders
    12. Dialogs
      1. File Selection Dialog
      2. The Color Chooser
  20. 18. More Swing Components
    1. Text Components
      1. The TextEntryBox Application
      2. Formatted Text
      3. Filtering Input
      4. Validating Data
      5. Say the Magic Word
      6. Sharing a Data Model
      7. HTML and RTF for Free
      8. Managing Text Yourself
    2. Focus Navigation
      1. Trees
      2. Nodes and Models
      3. Save a Tree
      4. Tree Events
      5. A Complete Example
    3. Tables
      1. A First Stab: Freeloading
      2. Round Two: Creating a Table Model
      3. Round Three: A Simple Spreadsheet
      4. Sorting and Filtering
      5. Printing JTables
    4. Desktops
    5. Pluggable Look-and-Feel
    6. Creating Custom Components
      1. Generating Events
      2. A Dial Component
      3. Model and View Separation
  21. 19. Layout Managers
    1. FlowLayout
    2. GridLayout
    3. BorderLayout
    4. BoxLayout
    5. CardLayout
    6. GridBagLayout
      1. The GridBagConstraints Class
      2. Grid Coordinates
      3. The fill Constraint
      4. Spanning Rows and Columns
      5. Weighting
      6. Anchoring
      7. Padding and Insets
      8. Relative Positioning
      9. Composite Layouts
    7. Other Layout Managers
    8. Absolute Positioning
  22. 20. Drawing with the 2D API
    1. The Big Picture
    2. The Rendering Pipeline
    3. A Quick Tour of Java 2D
      1. Filling Shapes
      2. Drawing Shape Outlines
      3. Convenience Methods
      4. Drawing Text
      5. Drawing Images
      6. The Whole Iguana
    4. Filling Shapes
      1. Solid Colors
      2. Color Gradients
      3. Textures
      4. Desktop Colors
    5. Stroking Shape Outlines
    6. Using Fonts
      1. Font Metrics
    7. Displaying Images
      1. The Image Class
      2. Image Observers
      3. Scaling and Size
    8. Drawing Techniques
      1. Double Buffering
      2. Limiting Drawing with Clipping
      3. Offscreen Drawing
    9. Printing
  23. 21. Working with Images and Other Media
    1. Loading Images
      1. ImageObserver
      2. MediaTracker
      3. ImageIcon
      4. ImageIO
    2. Producing Image Data
      1. Drawing Animations
      2. BufferedImage Anatomy
      3. Color Models
      4. Creating an Image
      5. Updating a BufferedImage
    3. Filtering Image Data
      1. How ImageProcessor Works
      2. Converting an Image to a BufferedImage
      3. Using the RescaleOp Class
      4. Using the AffineTransformOp Class
    4. Saving Image Data
    5. Simple Audio
    6. Java Media Framework
  24. 22. JavaBeans
    1. What’s a Bean?
      1. What Constitutes a Bean?
    2. The NetBeans IDE
      1. Installing and Running NetBeans
    3. Properties and Customizers
    4. Event Hookups and Adapters
      1. Taming the Juggler
      2. Molecular Motion
    5. Binding Properties
      1. Constraining Properties
    6. Building Beans
      1. The Dial Bean
      2. Design Patterns for Properties
    7. Limitations of Visual Design
    8. Serialization Versus Code Generation
    9. Customizing with BeanInfo
      1. Getting Properties Information
    10. Handcoding with Beans
      1. Bean Instantiation and Type Management
      2. Working with Serialized Beans
      3. Runtime Event Hookups with Reflection
    11. BeanContext and BeanContextServices
    12. The Java Activation Framework
    13. Enterprise JavaBeans and POJO-Based Enterprise Frameworks
  25. 23. Applets
    1. The Politics of Browser-Based Applications
    2. Applet Support and the Java Plug-in
    3. The JApplet Class
      1. Applet Lifecycle
      2. The Applet Security Sandbox
      3. Getting Applet Resources
      4. The <applet> Tag
      5. Attributes
      6. Parameters
      7. ¿Habla Applet?
      8. The Complete <applet> Tag
      9. Loading Class Files
      10. Packages
      11. appletviewer
    4. Java Web Start
    5. Conclusion
  26. 24. XML
    1. The Butler Did It
    2. A Bit of Background
      1. Text Versus Binary
      2. A Universal Parser
      3. The State of XML
      4. The XML APIs
      5. XML and Web Browsers
    3. XML Basics
      1. Attributes
      2. XML Documents
      3. Encoding
      4. Namespaces
      5. Validation
      6. HTML to XHTML
    4. SAX
      1. The SAX API
      2. Building a Model Using SAX
      3. XMLEncoder/Decoder
    5. DOM
      1. The DOM API
      2. Test-Driving DOM
      3. Generating XML with DOM
      4. JDOM
    6. XPath
      1. Nodes
      2. Predicates
      3. Functions
      4. The XPath API
      5. XMLGrep
    7. XInclude
      1. Enabling XInclude
    8. Validating Documents
      1. Using Document Validation
      2. DTDs
      3. XML Schema
      4. The Validation API
    9. JAXB Code Binding and Generation
      1. Annotating Our Model
      2. Generating a Java Model from an XML Schema
      3. Generating an XML Schema from a Java Model
    10. Transforming Documents with XSL/XSLT
      1. XSL Basics
      2. Transforming the Zoo Inventory
      3. XSLTransform
      4. XSL in the Browser
    11. Web Services
    12. The End of the Book
  27. A. The Eclipse IDE
    1. The IDE Wars
    2. Getting Started with Eclipse
      1. Importing the Learning Java Examples
    3. Using Eclipse
      1. Getting at the Source
      2. The Lay of the Land
      3. Running the Examples
      4. Building the Ant-Based Examples
      5. Loner Examples
    4. Eclipse Features
      1. Coding Shortcuts
      2. Autocorrection
      3. Refactoring
      4. Diffing Files
      5. Organizing Imports
      6. Formatting Source Code
    5. Conclusion
  28. B. BeanShell: Java Scripting
    1. Running BeanShell
    2. Java Statements and Expressions
      1. Imports
    3. BeanShell Commands
    4. Scripted Methods and Objects
      1. Scripting Interfaces and Adapters
    5. Changing the Classpath
    6. Learning More . . .
  29. Glossary
  30. Index
  31. About the Authors
  32. Colophon
  33. Copyright
O'Reilly logo

Loading Images

One of the challenges in building software for networked applications is that data is not always instantly available. Since some of Java’s roots are in Internet applications such as web browsers, its image handling APIs were designed specifically to accommodate the fact that images might take some time to load over a slow network, providing for detailed information about image-loading progress. While many client applications do not require handling of image data in this way, it’s still useful to understand this mechanism if for no other reason than it appears in the most basic image-related APIs. The Swing toolkit adds its own layer of image handling over this with components such as ImageIcon, which encapsulates an image source for you. After reading this chapter, you’ll have an understanding of how the layers fit together.

ImageObserver

In the previous chapter, we mentioned that all operations on image data (e.g., loading, drawing, scaling) allow you to specify an “image observer” object as a participant. An image observer implements the ImageObserver interface, allowing it to receive notification as information about the image becomes available. The image observer is essentially a callback that is notified progressively as the image is loaded. For a static image, such as a GIF or JPEG data file, the observer is notified as chunks of image data arrive and also when the entire image is complete. For a video source or animation (e.g., GIF89), the image observer is notified at the end of each frame as the continuous stream of pixel data is generated.

The image observer can do whatever it wants with this information. For example, in the last chapter we used the image observer built into the base Component class. Although you probably didn’t see it happen in our examples, the Component image observer invoked repaint() for us each time a new section of the image became available so that the picture, if it had taken a long time to load, would have displayed progressively. A different kind of image observer might have waited for the entire image before telling the application to display it; yet another use for an observer might be to update a loading meter showing how far the image loading had progressed.

To be an image observer, implement the imageUpdate() method, which is defined by the java.awt.image.ImageObserver interface:

    public boolean imageUpdate(Image image, int flags, int x, int y,
                               int width, int height)

imageUpdate() is called by the graphics system, as needed, to pass the observer information about the construction of its view of the image. The image parameter holds a reference to the Image object in question. flags is an integer whose bits specify what information about the image is now available. The flag values are defined as static variables in the ImageObserver interface, as illustrated in this example:

    //file: ObserveImageLoad.java
    import java.awt.*;
    import java.awt.image.*;

    public class ObserveImageLoad {

      public static void main( String [] args)
      {
       ImageObserver myObserver = new ImageObserver() {
          public boolean imageUpdate(
             Image image, int flags, int x, int y, int width, int height)
          {
             if ( (flags & HEIGHT) !=0 )
               System.out.println("Image height = " + height );
             if ( (flags & WIDTH ) !=0 )
               System.out.println("Image width = " + width );
             if ( (flags & FRAMEBITS) != 0 )
               System.out.println("Another frame finished.");
             if ( (flags & SOMEBITS) != 0 )
                System.out.println("Image section :"
                    + new Rectangle( x, y, width, height ) );
             if ( (flags & ALLBITS) != 0 )
               System.out.println("Image finished!");
             if ( (flags & ABORT) != 0 )
               System.out.println("Image load aborted...");
             return true;
         }
       };

        Toolkit toolkit = Toolkit.getDefaultToolkit();
        Image img = toolkit.getImage( args[0] );
        toolkit.prepareImage( img, -1, -1, myObserver );
      }
    }

Run the example, supplying an image file as the command-line argument and observe the output. You’ll see a number of incremental messages about loading the image.

The flags integer determines which of the other parameters—x, y, width, and height—hold valid data and what that data means. To test whether a particular flag in the flags integer is set, we have to resort to some binary shenanigans—using the & (AND) operator). The width and height parameters play a dual role. If SOMEBITS is set, they represent the size of the chunk of the image that has just been delivered. If HEIGHT or WIDTH is set, however, they represent the overall image dimensions. Finally, imageUpdate() returns a boolean value indicating whether or not it’s interested in future updates.

In this example, after requesting the Image object with getImage(), we kick-start the loading process with the Toolkit’s prepareImage() method, which takes our image observer as an argument. Using an Image API method such as drawImage(), scaleImage(), or asking for image dimensions with getWidth() or getHeight() will also suffice to start the operation. Remember that although the getImage() method created the image object, it doesn’t begin loading the data until one of the image operations requires it.

The example shows the lowest-level general mechanism for starting and monitoring the process of loading image data. You should be able to see how we could implement all sorts of sophisticated image loading and tracking schemes with this. The two most important strategies (to draw an image progressively, as it’s constructed, or to wait until it’s complete and draw it in its entirety) are handled for us. We have already seen that the Component class implements the first scheme. Another class, java.awt.MediaTracker, is a general utility that tracks the loading of a number of images or other media types for us. We’ll look at it in the next section.

MediaTracker

java.awt.MediaTracker is a utility class that simplifies life if we have to wait for one or more images to be loaded completely before they’re displayed. A MediaTracker monitors the loading of an image or a group of images and lets us check on them periodically or wait until they are finished. MediaTracker implements the ImageObserver interface that we just discussed, allowing it to receive image updates.

The following code snippet illustrates how to use a MediaTracker to wait while an image is prepared:

    //file: StatusImage.java
    import java.awt.*;
    import javax.swing.*;

    public class StatusImage extends JComponent
    {
      boolean loaded = false;
      String message = "Loading...";
      Image image;

      public StatusImage( Image image ) { this.image = image; }

      public void paint(Graphics g) {
        if (loaded)
            g.drawImage(image, 0, 0, this);
        else {
          g.drawRect(0, 0, getSize().width - 1, getSize().height - 1);
          g.drawString(message, 20, 20);
        }
      }
      public void loaded() {
        loaded = true;
        repaint();
      }
      public void setMessage( String msg ) {
        message = msg;
        repaint();
      }

      public static void main( String [] args ) {
        JFrame frame = new JFrame("TrackImage");
        Image image = Toolkit.getDefaultToolkit().getImage( args[0] );
        StatusImage statusImage = new StatusImage( image );
        frame.add( statusImage );
        frame.setSize(300,300);
        frame.setVisible(true);

        MediaTracker tracker = new MediaTracker( statusImage );
        int MAIN_IMAGE = 0;
        tracker.addImage( image, MAIN_IMAGE );
        try {
            tracker.waitForID( MAIN_IMAGE ); }
        catch (InterruptedException e) {}
        if ( tracker.isErrorID( MAIN_IMAGE ) )
            statusImage.setMessage( "Error" );
        else
            statusImage.loaded();
      }
    }

In this example, we created a trivial component called StatusImage that accepts an image and draws a text status message until it is told that the image is loaded. It then displays the image. The only interesting part here is that we use a MediaTracker to load the image data for us, simplifying our logic.

First, we create a MediaTracker to manage the image. The MediaTracker constructor takes a Component as an argument; this is supposed to be the component onto which the image is later drawn. This argument is somewhat of a holdover from earlier Java days with AWT. If you don’t have the component reference handy, you can simply substitute a generic component reference like so:

    Component comp = new Component();

After creating the MediaTracker, we assign it images to manage. Each image is associated with an integer that identifier we can use later for checking on its status or to wait for its completion. Multiple images can be associated with the same identifier, letting us manage them as a group. The value of the identifier is also meant to prioritize loading when waiting on multiple sets of images; lower IDs have higher priority. In this case, we want to manage only a single image, so we created one identifier called MAIN_IMAGE and passed it as the ID for our image in the call to addImage().

Next, we call the MediaTracker waitforID() routine, which blocks on the image, waiting for it to finish loading. If successful, we tell our example component to use the image and repaint. Another MediaTracker method, waitForAll(), waits for all images to complete, not just a single ID. It’s possible to be interrupted here by an InterruptedException. We should also test for errors during image preparation with isErrorID(). In our example, we change the status message if we find one.

The MediaTracker checkID() and checkAll() methods may be used to poll periodically the status of images loading, returning true or false to indicate whether loading is finished. The checkAll() method does this for the union of all images being loaded. Additionally, the statusID() and statusAll() methods return a constant indicating the status or final condition of an image load. The value is one of the MediaTracker constant values: LOADING, ABORTED, ERROR, or COMPLETE. For statusAll(), the value is the bitwise OR value of all of the various statuses.

This may seem like a lot of work to go through just to put up a status message while loading a single image. MediaTracker is more valuable when you are working with many raw images that have to be available before you can begin parts of an application. It saves implementing a custom ImageObserver for every application. For general Swing application work, you can use yet another simplification by employing the ImageIcon component to use a MediaTracker. This is covered next.

ImageIcon

In Chapter 17, we discussed Swing components that can work with images using the Icon interface. In particular, the ImageIcon class accepts an image filename or URL and can render it into a component. Internally, ImageIcon uses a MediaTracker to fully load the image in the call to its constructor. It can also provide the Image reference back. So, a shortcut to what we did in the last few sections—getting an image loaded fully before using it—would be:

    ImageIcon icon = new ImageIcon("myimage.jpg");
    Image image = icon.getImage();

This quirky approach saves a few lines of typing, but uses an icon in an odd way and is not very clear. ImageIcon also gives you direct access to the MediaTracker it’s using through the getMediaTracker() method or tells you the MediaTracker load status through the getImageLoadStatus() method. This returns one of the MediaTracker constants: ABORTED, ERROR, or COMPLETE.

ImageIO

As we mentioned in the introduction to Chapter 1, the javax.imageio package is a standard extension that deals with reading and writing many image formats. It is a part of the larger Java Advanced Imaging (JAI) API. This API supports advanced manipulation and display of images. While the AWT has a relatively fixed set of functionality, JAI is an extensible framework that accepts plug-ins for new image formats and features. The imageio portion of JAI is bundled with Java 1.4 and later, so we can take advantage of it on all current Java releases. ImageIO effectively supercedes the APIs we’ve talked about here with new ones for loading and monitoring image data, and although we won’t cover it in detail, we will discuss it briefly here for several reasons. First, it is fairly easy to use. Second, ImageIO natively works with BufferedImages and not just plain AWT Images. As we’ll discuss throughout the rest of this chapter, buffered images can expose their pixel data for you to read or manipulate. Finally, using ImageIO allows you both to load and save BufferedImages to files. The core AWT has no tools for encoding image data for saving to files.

Previously, we showed how easy it is to load an image with the static read() methods of the ImageIO class, which accept either a File, URL, or InputStream:

    File file = new File("/Users/pat/images/boojum.gif");
    BufferedImage bi = ImageIO.read( file );

In this example, we revealed that the type returned is actually a BufferedImage, which is a subtype of Image. The ImageIO.read() method, like the AWT getImage() method, automatically detects the image type and decodes it properly. Because ImageIO is extensible, it’s useful to be able to list the types of images it can decode. You get this information with the ImageIO.getReaderFormatNames() method, which returns an array of strings corresponding roughly to file extensions for the image types it understands. (ImageIO does not rely on file extensions to detect image types; rather, it looks at the content of the file.)

Images loaded by the ImageIO.read() methods are fully loaded before they are returned, so the method blocks until they are done. If you want more fine-grained information on the progress of image loading, you can use the IIOReadProgressListener interface of the javax.imageio.event package, which roughly corresponds to the AWT ImageObserver. To use it, you must delve a little deeper into the ImageIO API by first looking up an appropriate ImageReader object with which to register the listener:

    import javax.imageio.*;
    import javax.imageio.stream.*;
    import javax.imageio.event.*;
     
    File file = new File("image.jpg");
    ImageInputStream iis = ImageIO.createImageInputStream( file );
     
    Iterator readers = ImageIO.getImageReaders( iis );
    ImageReader reader = (ImageReader)readers.next(); // choose first one
     
    reader.addIIOReadProgressListener( readProgressListener );
    reader.setInput( iis, true );
    BufferedImage bi = reader.read( 0/*index*/ );

This code is fairly straightforward. The ReadProgressListener is used like any of the AWT or Swing event interfaces we’ve seen before. You can refer to the Javadoc for the exact methods you must implement.

Finally, in addition to the progress listener, two other listener APIs, IIOReadUpdateListener and IIOReadWarningListener, offer information on pixel changes (e.g., for progressive loading) and loading errors. There are also, of course, “write” versions of all of these tools that handle the flip side, saving image data. We’ll return to that topic later in this chapter.

The best content for your career. Discover unlimited learning on demand for around $1/day.