The Source for Java Technology Collaboration
User: Password:



Scott Violet

Scott Violet's Blog

Fun with Robot

Posted by zixle on May 02, 2005 at 06:18 AM | Comments (9)

In my last blog I mentioned we're nearly done with the baseline API for mustang. In verifying the baseline API work I initially took the approach of grabbing screenshots, dumping them in Paint and zooming in. Painful to say the least! There must be a better way.

Enter Robot

In addition to being able to inject mouse and keyboard events into the system java.awt.Robot gives you the ability render part of the desktop into an image. Exactly what I want. The following code grabs a screen shot returning a BufferedImage:
  Robot robot = new Robot();
  BufferedImage image = robot.createScreenCapture(new Rectangle(x, y, width, height));
So Robot gives me an image of part of the desktop, but I don't really want to continually do a keyboard gesture to create the image. I want the image to update as I move the mouse around.

Enter AWTEventListener

AWTEventListener can be used to listen to all events. Think of it as a way to globally install a *Listener. Using AWTEventListener I can determine when the mouse moves over any component. Here's the code for that:
  Toolkit toolkit = Toolkit.getDefaultToolkit();
  AWTEventListener listener = new AWTEventListener() {
    public void eventDispatched(AWTEvent event) {
      if (event.getID() == MouseEvent.MOUSE_MOVED) {
        mouseMoved(event);
      }
    }
  };
  toolkit.addAWTEventListener(new , AWTEvent.MOUSE_MOTION_EVENT_MASK);
Combining AWTEventListener with Robot I have a way to zoom in on part of my window as the cursor is being moved. Excellent! The following screen shot shows this in effect. The bottom area is the zoomed in component.

Magnification Screenshot

Here's the code:

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

public class MagnifyComponent extends JComponent {
    private int factor;
    private Image image;
    private int w;
    private int h;
    private Robot robot;

    MagnifyComponent() {
        try {
            robot = new Robot();
        } catch (AWTException e) {
        }
        this.factor = 6;
        Toolkit.getDefaultToolkit().addAWTEventListener(
            new EventHandler(), AWTEvent.MOUSE_MOTION_EVENT_MASK);
    }

    public void reshape(int x, int y, int w, int h) {
        super.reshape(x, y, w, h);
        updateImageSize();
    }

    private void updateImageSize() {
        int w = getWidth();
        int h = getHeight();
        image = null;
        this.w = w / factor / 2;
        this.h = h / factor / 2;
    }

    public void paintComponent(Graphics g) {
        if (isOpaque()) {
            g.setColor(getBackground());
            g.fillRect(0, 0, getWidth(), getHeight());
        }
        if (image != null) {
            g.drawImage(image, 0, 0, w * factor * 2, h * factor * 2,
                        0, 0, w + w, h + h, null);
        }
    }

    private void updateImage(int x, int y) {
        if (w > 0 && h > 0) {
            image = robot.createScreenCapture(new Rectangle(
                                                  x - w, y - h, w + w, h + h));
        }
        repaint();
    }

    private class EventHandler implements AWTEventListener {
        public void eventDispatched(AWTEvent event) {
            if (event.getID() == MouseEvent.MOUSE_MOVED) {
                MouseEvent me = (MouseEvent)event;
                Component source = me.getComponent();
                int x = me.getX();
                int y = me.getY();
                Point location = source.getLocationOnScreen();
                x += location.x;
                y += location.y;
                updateImage(x, y);
            }
        }
    }
}

I'm aware of at least one accessibility helper in Windows that zooms in on the desktop as you move the mouse, but I've found it a bit intrusive. In so far as the app always takes up a big chunk of the desktop, where as I really only wanted the zooming feature for this window.

Enjoy!

Warning: I'm sure there are performance issues with this code on slower/older machines. As this isn't for production and was only needed in testing, I did no testing other than on my machine. If you're to incorporate something like this in a real app do performance analysis first!


Bookmark blog post: del.icio.us del.icio.us Digg Digg DZone DZone Furl Furl Reddit Reddit
Comments
Comments are listed in date ascending order (oldest first) | Post Comment

  • I've used the robot the make a quick & dirty Print functionality.
    The Swing Print API was a little bit complex to my point of view, so I just grabed the image, orientate it if necessary, resize it to the maximum of the page (minus some margin) and send it to the printer...

    Posted by: lacostej on May 02, 2005 at 10:18 PM

  • Lacostej,
    Could you elaborate on what parts of the printing API are too complex?
    Thanks!
    -Scott

    Posted by: zixle on May 03, 2005 at 05:55 AM

  • I think I first saw a Swing based "jeweler's loupe" at this JavaOne Session. If you're a desktop developer with a J1O account, I recommend it. I also wish that there was a decent way to link to it.

    TS-1493(USA,2003) - Get Rich Quick: Taking Advantage of Java 2D[tm] API in Your Rich Client Application

    That approach would potentially look and perform better, although that's obviously not what you're after here. A nice magnifying glass control would be a useful addition to Swing (or SwingX). It would be handy both for presentations and accessibility. While it's not that hard to code yourself, there is no reason that everyone should have to.

    There a quite a few magnifying glass applets floating about.
    http://www.houseof3d.com/pete/applets/lens/lens2.html

    If you're interested in this sort of thing, check out Multivalent.
    http://multivalent.sourceforge.net/Browser/lens/lens-dump.html

    - Curt

    Posted by: coxcu on May 03, 2005 at 07:36 AM

  • I use http://www.digitalmantra.com/fatbits. Always like to plug a good program.
    Best,
    Laird

    Posted by: ljnelson on May 03, 2005 at 12:51 PM

  • A very nice little tool for Windows is zoom+
    http://www.gipsysoft.com/zoomplus/
    (full featured, free, source code available).
    But hey - it's much cooler to brew your own.

    Posted by: skelvin on May 04, 2005 at 02:50 PM

  • Some time ago I had to implement a rather advanced new layout on our web-client. It needed to look the same on both Windows and Linux. In order to do this I wrote a java application using robot to be able to zoom, take measures and check colors. It can also be used to copy all or a part of the screen. Because I wrote it on my spare time the application and sourcecode is free for all to use. (It's also webstartable)

    Check out Magnifier

    Posted by: wmjoers on May 06, 2005 at 04:08 AM

  • The robot api is a nice api and can be used on also none java application, but I miss two features:

    1. The image of the screen does not show the arrow of the mouse. It should be possible.

    2. It is difficult to position the cursor on an inputfield in an application and write several characters in the inputfield.
    Using the api for automation had been much easy'er if this is possible.

    Regards!

    Posted by: ostense on May 09, 2005 at 05:52 AM

  • ostense,
    I believe there are higher level APIs that use Robot to automate tasks like you're requesting. I'm not familiar with it, but take a look at Jemmy, it may do what you're after.
    -Scott

    Posted by: zixle on May 09, 2005 at 09:22 AM

  • wow power leveling
    wow powerleveling
    wow power leveling
    wow gold
    wow items
    feelingame.com
    wow tips
    Most Valuable WOW Power Leveling Service
    wow power leveling faq
    cheap wow power leveling
    wow power leveling
    wow powerleveling
    wow power lvl

    Posted by: huaguoli123 on December 06, 2007 at 05:27 PM





Powered by
Movable Type 3.01D
 Feed java.net RSS Feeds