Copyright Derek O'Reilly, Dundalk Institute of Technology (DkIT), Dundalk, Co. Louth, Ireland.
An ImageIcon is a fixed size image that can be attached to a JLabel, JButton or JTabbedPane.
To include icons in an applet you should create a sub-folder in the project's "src" folder called "images" (or any other name) and copy your images into this folder. Whenever you do a build, this folder will automatically be copied into the project's "build" folder. The location of the image that is loaded in the getResource() method will be the automatically created "images" folder that is relative to the class file.
ImageIcon Example (Run Applet)
import javax.swing.*; public class ImageIconDemo extends JApplet { @Override public void init() { this.setContentPane(new View()); } public class View extends JPanel { public View() { super(); // NOTE the the getResource() method looks for files relative to the location of the .class file final ImageIcon redIcon = new ImageIcon(getClass().getClassLoader().getResource("images/red_bullet.gif")); final JButton redButton = new JButton("Red Button"); final JLabel greenLabel = new JLabel("Green Label"); // the code below shows two different ways to assign the icon redButton.setIcon(redIcon); greenLabel.setIcon(new ImageIcon(getClass().getClassLoader().getResource("images/green_bullet.gif"))); // set the position of the redButton's text relative to an ImageIcon redButton.setHorizontalTextPosition(SwingConstants.LEFT); // LEFT means the text is on the left side this.add(redButton); this.add(greenLabel); } } }
We can use ImageIcons to display images. Labels can be set up to hold an ImageIcon and no text. This is a useful way to display images. However, the image inside the ImageIcon is fixed and cannot be minipulated once it has be initialised. In particular, an ImageLabel will not resize itself to fit it holding component. Instead, the compoent will resize to fit an ImageLabel. This means that ImageIcons need to be the correct size before they are used in code. The example below shows two labels automatically resizing to accomodate their respective ImageIcons.
Automatic Resizing of Labels to Accomodate ImageIcon Size Example: (Run Applet)
import javax.swing.*; public class ImageIconSizeDemo extends JApplet { @Override public void init() { this.setContentPane(new View()); } public class View extends JPanel { public View() { super(); final JLabel redLabel = new JLabel(new ImageIcon(getClass().getClassLoader().getResource("images/red_bullet.gif"))); final JLabel koalaLabel = new JLabel(new ImageIcon(getClass().getClassLoader().getResource("images/koala.jpg"))); this.add(redLabel); this.add(koalaLabel); } } }
We can use the Image class to overcome the limitations of ImageIcons. Images can be drawn onto any surface and they can be resized. We shall see later that the pixels in an image can be directly minipulated.
Java supports JPEG, GIF and PNG bitmapped graphics files. Applets do not support Microsoft .BMP files.
There are two ways to load an image.
The example below shows the use of the JApplet.getImage() and the ImageIcon.getImage() methods.
Run example: (Run Applet)
import java.awt.*; import javax.swing.*; public class GetImageDemo extends JApplet { @Override public void init() { this.setContentPane(new View()); } public class View extends JPanel { public View() { super(); } @Override public void paintComponent(Graphics g) { // Note: getDocumentBase() returns the folder that the applet's parent .html document resides in. final Image appletImage = getImage(getDocumentBase(), "classes/images/red_bullet.gif"); final Image iconImage = new ImageIcon(getClass().getClassLoader().getResource("images/green_bullet.gif")).getImage(); g.drawImage(appletImage, 0, 0, 100, 100, this); g.drawImage(iconImage, 150, 0, 100, 100, this); } } }
Use the drawImage() method to display the Image. The drawImage() method draws the specified image with its top left corner at (x, y) in the graphics context's coordinate space.
The drawImage() method can also be used for scaling.
For example: (Run Applet)
import javax.swing.*; import java.awt.*; public class DrawImageDemo extends JApplet { @Override public void init() { this.setContentPane(new View()); } public class View extends JPanel { public View() { super(); } @Override public void paintComponent(Graphics g) { final Image gif = (new ImageIcon(getClass().getClassLoader().getResource("images/world.gif"))).getImage(); final int width = gif.getWidth(this); final int height = gif.getHeight(this); g.drawImage(gif, 1, 1, width, height, this); g.drawImage(gif, 1, height + 5, width * 4, height / 2, this); } } }
Java uses threads to load image files. Rather than having to wait for an image file to be loaded, an applet will assign a thread to load the image file. The applet is then free to continue and do other things.
It might take a considerable length of time to load a graphics file over the WWW. We can use a MediaTracker to avoid the gradual building up of the graphics image.
The MediaTracker class traces the status of graphics files.
To use the MediaTracker, create an instance of the MediaTracker class and then call the addImage() method for each image to be tracked by the MediaTracker.
A MediaTracker can have more than one image assigned to it. Each image can be assigned a unique identifier.
The identifier:
The syntax for addImage() is:
addlmage(Image image, int id)addImage(Image image, int id, int w, int h)
To check if a graphics files assigned to a MediaTracker has been loaded use:
boolean checkID(int id)
To check if all the graphics files assigned to a MediaTracker have been loaded use:
boolean checkAll()
To wait for all the graphics files assigned to a specific MediaTracker ID to be loaded use:
waitForID(int id) // wait indefinitely boolean waitForID(int id, 1ong ms) // the maximum number of miliseconds to wait. // If it times out return false
To wait for all the graphics files assigned to a MediaTracker to be loaded use:
waitForAll() // wait indefinitely boolean waitForAll(1ong ms) // the maximum number of miliseconds to wait. // If it times out return false
For example: (Run Applet)
import java.awt.*; import javax.swing.*; public class MediaTrackerDemo extends JApplet { @Override public void init() { this.setContentPane(new View()); } public class View extends JPanel { public View() { super(); } @Override public void paintComponent(Graphics g) { final Image gif = new ImageIcon(getClass().getClassLoader().getResource("images/world.gif")).getImage(); final MediaTracker gifTracker = new MediaTracker(this); final int trackerId = 1; gifTracker.addImage(gif, trackerId); try { gifTracker.waitForID(trackerId); } catch (InterruptedException e) { } final int width = gif.getWidth(this); final int height = gif.getHeight(this); g.drawImage(gif, 1, 1, this); g.drawImage(gif, 1, height + 5, width * 4, height / 2, this); } } }
An animation is a sequence of graphics images. Use an array of Images to hold the frames of an animation.
For example: (Run Applet)
import java.awt.*; import javax.swing.*; public class AnimationDemo extends JApplet { private final View view = new View(); @Override public void init() { this.setContentPane(this.view); } @Override public void start() { this.view.setCurImage(0); // reset animation to first image } public class View extends JPanel { private final int numImages = 18; private final Image gif[] = new Image[numImages]; private int curImage = 0; public View() { super(); for (int i = 0; i < this.numImages; i++) { this.gif[i] = new ImageIcon(getClass().getClassLoader().getResource("images/img" + i + ".gif")).getImage(); } } public void setCurImage(int curImage) { this.curImage = curImage; } @Override public void paintComponent(Graphics g) { g.drawImage(this.gif[this.curImage], 1, 1, this); if (++this.curImage == this.numImages) { this.curImage = 0; } try { Thread.sleep(80); } catch (InterruptedException e) { } this.repaint(); } } }
We can avoid the jerky build-up of images by using a MediaTracker.
For Example. (Run Applet)
import java.awt.*; import javax.swing.*; public class MediaTrackerAnimationDemo extends JApplet { private final View view = new View(); @Override public void init() { this.setContentPane(this.view); } @Override public void start() { this.view.setCurImage(0); // reset animation to first image } public class View extends JPanel { private final int numImages = 18; private final Image gif[] = new Image[numImages]; private final MediaTracker animationTracker = new MediaTracker(this); private int curImage = 0; public View() { super(); for (int i = 0; i < this.numImages; i++) { this.gif[i] = new ImageIcon(getClass().getClassLoader().getResource("images/img" + i + ".gif")).getImage(); animationTracker.addImage(this.gif[i], 1); } } public void setCurImage(int curImage) { this.curImage = curImage; } @Override public void paintComponent(Graphics g) { if (this.animationTracker.checkID(1, true)) { g.drawImage(this.gif[this.curImage], 1, 1, this); if (++this.curImage == this.numImages) { this.curImage = 0; } } else { g.drawString("Loading images...", 100, 100); } if (++this.curImage == this.numImages) { this.curImage = 0; } try { Thread.sleep(80); } catch (InterruptedException e) { } this.repaint(); } } }
The default super.paintComponent() method clears its background. Therefore, whatever was drawn previously will be overwritten on the screen after the next call to painComponent(). This is show in the example below.
Example of clearing the background when calling paintComponent() method (Run Applet)
import java.awt.*; import java.awt.event.*; import javax.swing.*; public class PaintWithCallToSuperDemo extends JApplet { @Override public void init() { this.setContentPane(new View()); } public class View extends JPanel implements MouseListener, MouseMotionListener { private final Image gif; private final int width = 100; private final int height = 100; private int curX = 1; private int curY = 1; private final Rectangle rect = new Rectangle(curX, curY, width, height); private int offsetX = 0; private int offsetY = 0; public View() { super(); this.gif = new ImageIcon(getClass().getClassLoader().getResource("images/world.gif")).getImage(); this.setBackground(Color.red); this.addMouseListener(this); this.addMouseMotionListener(this); } @Override public void paintComponent(Graphics g) { super.paintComponent(g); g.drawImage(this.gif, 0, 0, getWidth(), getHeight(), this); g.drawImage(this.gif, this.curX, this.curY, this.width, this.height, this); } @Override public void mouseDragged(MouseEvent e) { final int x = e.getX(); final int y = e.getY(); if (this.rect.contains(x, y)) { this.curX = x - this.offsetX; this.curY = y - this.offsetY; this.rect.setBounds(this.curX, this.curY, this.width, this.height); this.repaint(); } } @Override public void mousePressed(MouseEvent e) { final int x = e.getX(); final int y = e.getY(); if (this.rect.contains(x, y)) { this.offsetX = x - this.curX; this.offsetY = y - this.curY; } } @Override public void mouseClicked(MouseEvent me) { } @Override public void mouseReleased(MouseEvent me) { } @Override public void mouseEntered(MouseEvent me) { } @Override public void mouseExited(MouseEvent me) { } @Override public void mouseMoved(MouseEvent me) { } } }
Removing the call to super.paintComponent() method will result in whatever was drawn previously remaining on the screen. This is show in the example below.
Example of leaving the background in tack between calls to the paintComponent() method (Run Applet)
import java.awt.*; import java.awt.event.*; import javax.swing.*; public class PaintWithoutCallToSuperDemo extends JApplet { @Override public void init() { this.setContentPane(new View()); } public class View extends JPanel implements MouseListener, MouseMotionListener { private final Image gif; private final int width = 100; private final int height = 100; private int curX = 1; private int curY = 1; private final Rectangle rect = new Rectangle(curX, curY, width, height); private int offsetX = 0; private int offsetY = 0; public View() { super(); this.gif = new ImageIcon(getClass().getClassLoader().getResource("images/world.gif")).getImage(); this.setBackground(Color.red); this.addMouseListener(this); this.addMouseMotionListener(this); } @Override public void paintComponent(Graphics g) { // super.paintComponent(g); g.drawImage(this.gif, 0, 0, getWidth(), getHeight(), this); g.drawImage(this.gif, this.curX, this.curY, this.width, this.height, this); } @Override public void mouseDragged(MouseEvent e) { final int x = e.getX(); final int y = e.getY(); if (this.rect.contains(x, y)) { this.curX = x - this.offsetX; this.curY = y - this.offsetY; this.rect.setBounds(this.curX, this.curY, this.width, this.height); this.repaint(); } } @Override public void mousePressed(MouseEvent e) { final int x = e.getX(); final int y = e.getY(); if (this.rect.contains(x, y)) { this.offsetX = x - this.curX; this.offsetY = y - this.curY; } } @Override public void mouseClicked(MouseEvent me) { } @Override public void mouseReleased(MouseEvent me) { } @Override public void mouseEntered(MouseEvent me) { } @Override public void mouseExited(MouseEvent me) { } @Override public void mouseMoved(MouseEvent me) { } } }
The Image class can be used for offscreen graphics.
Use the getGraphics() method to place a graphics context into an Image. The getGraphics() method can only be called for offscreen images, which must be created with the createImage() method.
To create an empty Image (double buffer), use the createImage() method from the Component class.
The syntax for createImage() is:
Image createImage(int width, int height)
An image map is an image that has hot areas that the user can click on to trigger an event. For example, when a user positions the mouse over a hot area a descriptive message can be displayed in the status area of the browser.
We can detect if the mouse is positioned over a Component (such as a Canvas) using the Component's contains() method.
We can draw a Rectangle or Polygon at any location on top of any Component. We can then use the Rectangle'sor Polygon's contains() method to detect that the mouse has moved over an area within a Component. Rectangles can be used to bound Images drawn on a Component's graphics context.
Image Map Example: (Run Applet)
import javax.swing.*; import java.awt.*; import java.awt.event.*; public class ImageMapDemo extends JApplet { @Override public void init() { this.setContentPane(new View()); } public class View extends JPanel implements MouseMotionListener { private final int x[] = { 177, 175, 191, 202, 209, 216, 215, 208, 196 }; private final int y[] = { 165, 250, 246, 239, 229, 218, 203, 185, 171 }; private final Polygon poly = new Polygon(this.x, this.y, 9); private final Rectangle rect = new Rectangle(125, 29, 56, 78); private final Image gif = new ImageIcon(getClass().getClassLoader().getResource("images/halfAdder.gif")).getImage(); public View() { super(); this.addMouseMotionListener(this); } @Override public void paintComponent(Graphics g) { g.drawImage(this.gif, 0, 0, this); } @Override public void mouseDragged(MouseEvent me) { } @Override public void mouseMoved(MouseEvent e) { final int x = e.getX(); final int y = e.getY(); if (this.rect.contains(x, y)) { showStatus("NOR gate selected"); } else if (this.poly.contains(x, y)) { showStatus("AND gate selected"); } else { showStatus("No gate selected"); } } } }
Copyright Derek O' Reilly, Dundalk Institute of Technology (DkIT), Dundalk, Co. Louth, Ireland.