Some reader favorites:
EJB fundamentals and session beans
Create a scrollable virtual desktop in Swing
Wizard API updated!
Tim Boudreau has released a new version of the Swing Wizard library (version 0.997) that fixes the WizardException bug reported in JavaWorld's recent Open Source Java Project profile. The article's examples have been reworked to test out the new, improved WizardException. Thanks, Tim, for this helpful fix!
Open Source Java Projects: The Wizard API
The java.awt.Robot class provides several opportunities for fun. One opportunity involves building a screen-capture utility. This Java Fun and Games installment presents a utility that uses Robot to capture the contents of the primary screen device.
This installment diverges from my previous installments by not focusing on an applet implementation. Instead, this article presents my screen-capture utility as a Swing application. After introducing this application from a GUI perspective, I explain key areas of its implementation.
My Capture application reveals a GUI that lets you select a portion of a captured image, crop that image to the selection's contents, and save the resulting image to a jpeg file. Figure 1 shows Capture's GUI with an example capture.

Figure 1. A red-and-white dashed rectangle identifies the current selection
Capture's GUI consists of a menu bar and a scrollable window that reveals the captured image. As shown in Figure 1, a selection rectangle (that you drag with the mouse) identifies a rectangular area of the captured image.
The menu bar presents File and Capture menus:
Three source files describe Capture's GUI: Capture.java (starts the application and constructs the GUI), ImageArea.java (describes a component that displays, and lets you select part of and crop a screen capture), and ImageFileFilter.java (restricts file-chooser selections to directories and jpeg filenames). In the sections below, I excerpt code fragments from
these source files to illustrate how Capture works.
To capture the screen with the Robot class, Capture must first create a Robot object. The Capture class's public static void main(String [] args) method attempts to create this object by invoking Robot's public Robot() constructor. If successful, a reference to a Robot configured to the primary screen device's coordinate system returns. If the platform does not support low-level control (which
is true of an environment without a screen device), a java.awt.AWTException is thrown. A java.lang.SecurityException is thrown if the platform doesn't grant permission to create a Robot. Hopefully, you will not encounter either exception.
Assuming a Robot object is created, main() invokes the Capture class's constructor to create the GUI. As part of its GUI creation, Capture obtains the dimensions of the primary screen
device by invoking dimScreenSize = Toolkit.getDefaultToolkit ().getScreenSize ();. Because Robot's public BufferedImage createScreenCapture(Rectangle screenRect) method, which is used to perform a screen capture, requires a java.awt.Rectangle argument, the constructor converts the java.awt.Dimension object to a Rectangle object via rectScreenSize = new Rectangle (dimScreenSize);. The Capture.java excerpt below calls createScreenCapture() when the Capture menu item's action listener is invoked:
// Hide Capture's main window so that it does not appear in
// the screen capture.
setVisible (false);
// Perform the screen capture.
BufferedImage biScreen;
biScreen = robot.createScreenCapture (rectScreenSize);
// Show Capture's main window for continued user interaction.
setVisible (true);
// Update ImageArea component with the new image and adjust
// the scrollbars.
ia.setImage (biScreen);
jsp.getHorizontalScrollBar ().setValue (0);
jsp.getVerticalScrollBar ().setValue (0);
You don't want Capture's GUI to hide whatever you are trying to capture. That is why the code fragment hides Capture's GUI
prior to making the capture. After obtaining a java.awt.image.BufferedImage that contains a copy of the screen's pixels, the code fragment shows the GUI and displays the contents of the BufferedImage via the image area component.
A selection rectangle is needed to select a sub-image from a captured image. The ImageArea class provides code to create, manipulate, and draw that rectangle. As shown in the ImageArea.java excerpt below, that class's constructor creates the selection rectangle as a Rectangle instance, creates java.awt.BasicStroke and java.awt.GradientPaint objects to define the appearance of the rectangle's outline (to keep it distinct from the underlying image), and registers
mouse and mouse-motion listeners that let you manipulate the selection rectangle:
// Create a selection Rectangle. It's better to create one Rectangle
// here than a Rectangle each time paintComponent() is called, to reduce
// unnecessary object creation.
rectSelection = new Rectangle ();
// Define the stroke for drawing selection rectangle outline.
bs = new BasicStroke (5, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND,
0, new float [] { 12, 12 }, 0);
// Define the gradient paint for coloring selection rectangle outline.
gp = new GradientPaint (0.0f, 0.0f, Color.red, 1.0f, 1.0f, Color.white,
true);
// Install a mouse listener that sets things up for a selection drag.
MouseListener ml;
ml = new MouseAdapter ()
{
public void mousePressed (MouseEvent e)
{
// When you start Capture, there is no captured image.
// Therefore, it makes no sense to try and select a sub-image.
// This is the reason for the if (image == null) test.
if (image == null)
return;
destx = srcx = e.getX ();
desty = srcy = e.getY ();
repaint ();
}
};
addMouseListener (ml);
// Install a mouse motion listener to update the selection rectangle
// during drag operations.
MouseMotionListener mml;
mml = new MouseMotionAdapter ()
{
public void mouseDragged (MouseEvent e)
{
// When you start Capture, there is no captured image.
// Therefore, it makes no sense to try and select a
// sub-image. This is the reason for the if (image == null)
// test.
if (image == null)
return;
destx = e.getX ();
desty = e.getY ();
repaint ();
}
};
addMouseMotionListener (mml);
The mouse event handler sets destx and srcx to the same horizontal mouse coordinate when you press a mouse button. It does the same for the vertical mouse coordinate.
The source and destination variables are made equal to signify that any displayed selection rectangle should be removed. This
is carried out by calling repaint(), which results in public void paintComponent(Graphics g) being called. That method compares srcx with destx, and srcy with desty. If they differ, a selection rectangle is drawn:
// Draw the selection rectangle if present.
if (srcx != destx || srcy != desty)
{
// Compute upper-left and lower-right coordinates for selection
// rectangle corners.
int x1 = (srcx < destx) ? srcx : destx;
int y1 = (srcy < desty) ? srcy : desty;
int x2 = (srcx > destx) ? srcx : destx;
int y2 = (srcy > desty) ? srcy : desty;
// Establish selection rectangle origin.
rectSelection.x = x1;
rectSelection.y = y1;
// Establish selection rectangle extents.
rectSelection.width = (x2-x1)+1;
rectSelection.height = (y2-y1)+1;
// Draw selection rectangle.
Graphics2D g2d = (Graphics2D) g;
g2d.setStroke (bs);
g2d.setPaint (gp);
g2d.draw (rectSelection);
}
Before the selection rectangle can be drawn, its upper-left and lower-right corners must be identified to determine the rectangle's
origin and extents. So that you can drag the selection rectangle in various directions (a lower-right or an upper-left direction,
for example), the minimums of srcx/destx and srcy/desty are obtained to identify the upper-left corner. Similarly, the maximums of their values are obtained to identify the lower-right
corner.
After selecting a sub-image, you'll want to crop the captured image to that sub-image. Image cropping begins in the Crop menu
item's action listener, which requests that ImageArea crop a captured image to the selected sub-image. If successful, the listener resets ImageArea's scrollbars. If not successful, the listener presents an "Out of bounds" error message via a dialog box:
// Crop ImageArea component and adjust the scrollbars if
// cropping succeeds.
if (ia.crop ())
{
jsp.getHorizontalScrollBar ().setValue (0);
jsp.getVerticalScrollBar ().setValue (0);
}
else
showError ("Out of bounds.");
Because a crop operation does not resize Capture's GUI, the main window's background can be seen along with the resulting image (after an initial crop). Figure 2 reveals that it is possible to select part of that background while selecting part of the image.

Figure 2. An attempt to select more than the image
The main window's background pixels are not part of the captured image; including them in a cropped image is impossible. For that reason, cropping fails and an "Out of bounds" error message displays whenever background pixels are included in a selection.
| Subject | Replies |
Last post
|
|
By TeoS |
1 |
06/11/07 05:40 AM
by EugeneT |
|
By sandip |
0 |
02/09/07 02:27 AM
by sandip |
|
By JavaWorld
|
0 |
10/05/06 09:33 AM
by JavaWorld |
Free Download - 5 Minute Product Review. When slow equals Off: Manage the complexity of Web applications - Symphoniq
![]()
Free Download - 5 Minute Product Review. Realize the benefits of real user monitoring in less than an hour. - Symphoniq