288
|
Chapter 8, Rendering
#56 Create a Magnifying Glass Component
HACK
Build the Magnifying Glass
The DetachedMagnifyingGlass will need to keep track of the Component it’s
viewing, the current mouse location in that component, a zoom factor, and
its own size. It will also need an instance of the AWT
Robot
for taking screen
grabs. The other thing it needs to do is to have a
MouseMotionListener
, so
that it will get updates on the cursor’s position and, when it changes, do a
new grab and
repaint( )
.
The
DetachedMagnifyingGlass code is shown in Example 8-1.
Example 8-1. JComponent to provide a magnified view of another JComponent
public class DetachedMagnifyingGlass extends JComponent
implements MouseMotionListener {
double zoom;
JComponent comp;
Point point;
Dimension mySize;
Robot robot;
public DetachedMagnifyingGlass (JComponent comp,
Dimension size,
double zoom) {
this.comp = comp;
// flag to say don't draw until we get a MouseMotionEvent
point = new Point (-1, -1);
comp.addMouseMotionListener(this);
this.mySize = size;
this.zoom = zoom;
// if we can't get a robot, then we just never
// paint anything
try {
robot = new Robot( );
} catch (AWTException awte) {
System.err.println ("Can't get a Robot");
awte.printStackTrace( );
}
}
public void paint (Graphics g) {
if ((robot == null) || (point.x == -1))
{
g.setColor (Color.blue);
g.fillRect (0, 0, mySize.width, mySize.height);
return;
}
Rectangle grabRect = computeGrabRect( );
BufferedImage grabImg = robot.createScreenCapture (grabRect);
Image scaleImg =
grabImg.getScaledInstance (mySize.width, mySize.height,
Image.SCALE_FAST);
Create a Magnifying Glass Component #56
Chapter 8, Rendering
|
289
HACK
Looking at the code, the constructor takes the source component, a size for
the magnified component, and a zoom level. It assigns these to its instance
variables, and sets up a
MouseMotionListener to get updates regarding the
cursor position, which is initialized to a “don’t paint me” dummy value of
(-1, -1). It also builds the AWT Robot. Since this can fail on some OSes or
under certain security situations,
the robot == null case will have to be han-
dled gracefully in the painting routine.
The
paint( ) method begins by checking for the two conditions that indi-
cate the mangnified component can’t be painted: if there’s no
Robot or if the
cursor has never entered the source component. In either of these cases, the
magnified component simply fills itself with blue and returns.
On the other hand, if valid data is available, the magnifier needs to figure out
what portion of the source component to grab. For simplicity, you can com-
pute a rectangle whose upper left is the current cursor location. The width
and height of the rectangle are computed by multiplying the zoom factor by
the magnifying component’s height and width. So, for a zoom of
1.0, the
grab is exactly the size of the magnifier. For a zoom of
0.5, it grabs half the
width and half the height, and for
2.0, it grabs twice the width and height.
g.drawImage (scaleImg, 0, 0, null);
}
private Rectangle computeGrabRect( ) {
// width, height are size of this comp / zoom
int grabWidth = (int) ((double) mySize.width / zoom);
int grabHeight = (int) ((double) mySize.height / zoom);
// upper-left corner is current point
return new Rectangle (point.x, point.y, grabWidth, grabHeight);
}
public Dimension getPreferredSize( ) { return mySize; }
public Dimension getMinimumSize( ) { return mySize; }
public Dimension getMaximumSize( ) { return mySize; }
// MouseMotionListener implementations
public void mouseMoved (MouseEvent e) {
Point offsetPoint = comp.getLocationOnScreen( );
e.translatePoint (offsetPoint.x, offsetPoint.y);
point = e.getPoint( );
repaint( );
}
public void mouseDragged (MouseEvent e) {
mouseMoved (e);
}
}
Example 8-1. JComponent to provide a magnified view of another JComponent

Get Swing Hacks now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.