Home > Articles > Programming > Java

  • Print
  • + Share This
Like this article? We recommend

Custom Cursor Shapes

Have you ever wanted to design your own custom mouse cursor shape and implement it as an official AWT mouse cursor? Now you can. In recent months, I conducted an experiment in which I designed a 32x32 pixel mouse cursor shape, installed this mouse cursor shape into the AWT, and wrote a pair of programs to demonstrate the new mouse cursor.

To begin, I hauled out my paint program, switched its display mode to zoom (so I could more accurately plot pixels), set image dimensions to 32x32, set the color mode to 256 color grayscale, and started to get artistic. The result appears in Figure 2.

Figure 2

The result of my pixel-plotting exercise led to a mouse cursor shape with four arrows pointing to an X.

Look carefully at Figure 2. Notice the white pixels surrounding the X. These pixels (along with the black pixels) appear when the mouse cursor shape is displayed. (The white pixels enhance the visibility of the X.) However, the dark gray pixels will not appear, because dark gray is the transparent color for this image.

NOTE

Although my mouse cursor shape has a width of 32 pixels and a height of 32 pixels, I could just as easily create a 16x16 pixel image—because the AWT supports mouse cursor shapes of either 32x32 or 16x16 pixel dimensions.

After designing the mouse cursor shape and selecting its transparent color, I saved this image to a file called newcursor32x32.gif, placed the file in an appropriate directory, and modified an AWT configuration file so that the AWT would recognize the file's mouse cursor shape. On my Windows 98 SE machine, I ended up copying newcursor32x32.gif to c:\Program Files\Javasoft\JRE\1.3\lib\images\cursors. In other words, I copied this file to my installed Java runtime environment's cursors directory.

The AWT configuration file (located in the cursors directory) is called cursors.properties. To tell the AWT about my new mouse cursor shape, I added the following three entries to this file:

Cursor.NewCursor.32x32.File=newcursor32x32.gif
Cursor.NewCursor.32x32.HotSpot=15,15

Cursor.NewCursor.32x32.Name=newcursor32x32

These entries identify the mouse cursor's file, its hotspot, and the name by which the mouse cursor is known to the AWT.

NOTE

A hotspot is a coordinate pair that identifies that part of the mouse cursor shape used by the AWT in determining where the mouse cursor is located—such as what component the mouse cursor is hovering over—when the left mouse button is clicked. In my cursors.properties entry, the first 15 is the hotspot's horizontal position and the second 15 is the hotspot's vertical position.

To assign the new mouse cursor to a component, I discovered that you must first obtain a reference to an object associated with the mouse cursor, and assign this reference to a Cursor variable. It turns out that this task is accomplished by calling Cursor's getSystemCustomCursor method—as demonstrated by the following code fragment:

Cursor c = Cursor.getSystemCustomCursor ("NewCursor.32x32");

The argument passed to getSystemCustomCursor must match the cursor.properties entry name (except for the Cursor. prefix). Also, because getSystemCustomCursor is capable of throwing an AWTException object, it's important to either handle this exception or pass the buck by appending AWTException to the throws clause of the calling method's signature.

After designing the mouse cursor shape and installing this shape into the AWT, I created a pair of programs, one AWT-specific and one Swing-specific, to demonstrate the new mouse cursor shape. (I realize that this article is concerned with AWT tips, but it doesn't hurt to show that you can also use this tip with Swing.) Listing 3 presents source code for an AWT application (called CustomCursorShape1) that demonstrates the new mouse cursor shape.

Listing 3  The CustomCursorShape1 application source code

// CustomCursorShape1.java

import java.awt.*;
import java.awt.event.*;

class CustomCursorShape1 extends Frame
{
   CustomCursorShape1 (String title)
   {
      super (title);

      addWindowListener
                (new WindowAdapter ()
                 {
                     public void windowClosing (WindowEvent e)
                     {
                        System.exit (0);
                     }
                 });

      Button b = new Button ("Move Cursor Over Me");

      try
      {
         Cursor c = Cursor.getSystemCustomCursor ("NewCursor.32x32");
         b.setCursor (c);
      }
      catch (AWTException e)
      {
         System.out.println (e);
      }

      Panel p = new Panel ();
      p.add (b);
      add (p);

      setSize (300, 65);

      setVisible (true);
   }

   public static void main (String [] args)
   {
      new CustomCursorShape1 ("Custom Cursor Shape (AWT-specific)");
   }
}

CustomCursorShape1's source code is pretty self-explanatory. Once it's compiled and the resulting byte codes are run, you'll see something similar to what appears in Figure 3.

Figure 3

CustomCursorShape1 demonstrates an AWT button with a custom mouse cursor shape hovering over this button.

To demonstrate using a custom mouse cursor shape in a Swing-based program, Listing 4 presents CustomCursorShape2's source code.

Listing 4  The CustomCursorShape2 application source code

// CustomCursorShape2.java

import javax.swing.*;

import java.awt.*;

class CustomCursorShape2 extends JFrame
{
   CustomCursorShape2 (String title)
   {
      super (title);

      setDefaultCloseOperation (EXIT_ON_CLOSE);

      JButton b = new JButton ("Move Cursor Over Me");

      try
      {
         Cursor c = Cursor.getSystemCustomCursor ("NewCursor.32x32");
         b.setCursor (c);
      }
      catch (AWTException e)
      {
         System.out.println (e);
      }

      JPanel p = new JPanel ();
      p.add (b);
      getContentPane ().add (p);

      setSize (300, 65);

      setVisible (true);
   }

   public static void main (String [] args)
   {
      new CustomCursorShape2 ("Custom Cursor Shape (Swing-specific)");
   }
}

As you can see, the CustomCursorShape1 and CustomCursorShape2 source code listings are nearly identical. Once you've compiled CustomCursorShape2's source code and run the resulting byte codes, you'll see something similar to what appears in Figure 4.

Figure 4

CustomCursorShape2 demonstrates a Swing button with a custom mouse cursor shape hovering over this button.

Although this tip has been successfully developed under SDK 1.3 and Windows 98 SE, I make no guarantees that it will work on other platforms.

As an exercise, can you create a colored custom mouse cursor shape (that is, a mouse cursor shape with pixels in red, blue, green, and so on)?

  • + Share This
  • 🔖 Save To Your Account