Sunday, 11 January 2009

Setting a custom cursor which doesn't get resized

When setting a custom cursor in Swing you shouldn't really rely on the createCustomCursor method to use your images in any respectful way. The behaviour of this method is to resize the image into the dimensions returned by the getBestCursorSize method, which on Windows XP always seems to return 32x32 pixels.

To me this seems pretty crap because the image is going to get resized at some point depending on the platform your app is being run on which will most likely make the cursor image look terrible, perhaps to the user, unusable. IMO the behaviour should be to create a new image of the dimensions of getBestCursorSize and draw the supplied image at point 0,0. This does cause a problem if your image is larger than the dimension but your would be screwed the default way anyway.

Implementation is below...
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.image.BufferedImage;

public class SizedCursor
{
public static Image getPreferredSizedCursor(
Image image)
{
Dimension bestDimension = Toolkit
.getDefaultToolkit()
.getBestCursorSize(
image
.getWidth(null),
image
.getHeight(null));

if (bestDimensionsEqualsImageSize(
image,
bestDimension))
{
return image;
}
else
{
BufferedImage resizedImage = new BufferedImage(
bestDimension.width,
bestDimension.height,
BufferedImage.TYPE_INT_ARGB);
Graphics2D g = (Graphics2D) resizedImage
.getGraphics();

g.drawImage(
image, 0,
0, null);

return resizedImage;
}
}

private static boolean bestDimensionsEqualsImageSize(
Image image,
Dimension bestDimension)
{
return bestDimension
.getWidth() == image
.getWidth(null)
&& bestDimension
.getHeight() == image
.getHeight(null);
}
}