Custom Pointers

Is it possible to import or create additional mouse pointer options? I just jumped through some hoops and did the same sort of thing with a floating image, but man, it would be easier if I could just change the pointer. Is there some java library available for us to do that?

Yeah, you can. Check out java.awt.Toolkit.createCustomCursor

The trick is to get the Image. You could do something like this:

javax.swing.ImageIcon(new java.net.URL("http://yourgateway:8080/gateway/images/myimage.png"))

Ok, I’m almost there, but can’t see where the “expecting 4 args but got 3” error is coming from. In Java examples where there is something like “new Point(0,0)”, what do I use for new?

Here is my code:

p = Point2D.Double(2,2)
#Point(2,2)
newCursor = javax.swing.ImageIcon(java.net.URL('http://localhost:8080/gateway/images/Builtin/icons/24/refresh.png'))
b = Toolkit.createCustomCursor(newCursor,p,'TEST')

I’ve tried a couple of different ways of defining Point, but I still get this error (Line 11 is Line 4 above):

ERROR [ActionAdapter-AWT-EventQueue-0] <HTML>Error executing script for event:&nbsp;<code><b>mousePressed</b></code><BR>on component:&nbsp;<code><b>ModulePB</b></code>.
Traceback (innermost last):
  File "<event:mousePressed>", line 11, in ?
TypeError: createCustomCursor(): expected 4 args; got 3

	at org.python.core.Py.TypeError(Py.java)
	at org.python.core.PyReflectedFunction.throwError(PyReflectedFunction.java)
	at org.python.core.PyReflectedFunction.throwArgCountError(PyReflectedFunction.java)
	at org.python.core.PyReflectedFunction.throwError(PyReflectedFunction.java)
	at org.python.core.PyReflectedFunction.__call__(PyReflectedFunction.java)
	at org.python.core.PyReflectedFunction.__call__(PyReflectedFunction.java)
	at org.python.core.PyObject.__call__(PyObject.java)
	at org.python.core.PyObject.invoke(PyObject.java)
	at org.python.pycode._pyx257.f$0(<event:mousePressed>:11)
	at org.python.pycode._pyx257.call_function(<event:mousePressed>)
	at org.python.core.PyTableCode.call(PyTableCode.java)
	at org.python.core.PyCode.call(PyCode.java)
	at org.python.core.Py.runCode(Py.java)

I don’t think the point is your problem, you need to do:

b = Toolkit.getDefaultToolkit().createCustomCursor(newCursor,p,'TEST')

createCustomCursor is not a static function, so in python-speak, it takes 4 arguments, the first being the instance of the Toolkit object.

I can’t answer you question re: the error but I can address the “new” issue.

There is no equivalent to the java “new” keyword in Jython. That’s because java is “static typed” and Jython is “dynamic typed”. New instances of an object must be created with the “new” keyword in java. Instances in Jython are created on the fly and don’t have to be created with a “new” keyword.

I’ll try playing with your error this evening, when I get a chance.

Thanks Mickey. Carl nailed it above. I’m going to give it a try tonight.

Here’s a more extensive code snippet:

import java.awt import javax.swing import java.net url = java.net.URL('http://localhost:8080/gateway/images/Builtin/icons/24/refresh.png') icon = javax.swing.ImageIcon(url) point = java.awt.Point(2,2) component = event.source.parent.getComponent("componentName") customCursor = java.awt.Toolkit.getDefaultToolkit().createCustomCursor(icon.getImage(),point,'refresh') component.setCursor(customCursor) To reset the cursor:

defaultCursor = java.awt.Cursor.getPredefinedCursor(java.awt.Cursor.DEFAULT_CURSOR) component.setCursor(defaultCursor)
Here’s a list of the predefined cursors:

[ul]DEFAULT_CURSOR
CROSSHAIR_CURSOR
TEXT_CURSOR
WAIT_CURSOR
SW_RESIZE_CURSOR
SE_RESIZE_CURSOR
NW_RESIZE_CURSOR
NE_RESIZE_CURSOR
N_RESIZE_CURSOR
S_RESIZE_CURSOR
W_RESIZE_CURSOR
E_RESIZE_CURSOR
HAND_CURSOR
MOVE_CURSOR[/ul]

You can get the component’s current cursor with the following line:

currentCursor = component.getCursor()

and set it back with this:

component.setCursor(currentCursor)

Very cool. Thanks Mickey.

I ended up with a different implementation, but with the same results. Is there a preference when it comes to using fully qualified names for methods? For instance, I normally use something like “from java.awt import Image” rather than “import java.awt” and then using java.awt.Image in the code. I have no good reason for doing this other than that’s how I learned to do it through trial and error and it saves a lot of typing when you use the paint component. :slight_smile: But otherwise, is one style better than another or is it a wash?

edit: Forgot to post my code.

from java.awt import Cursor
from java.awt import Toolkit
from java.awt import Image
from javax.swing import ImageIcon
from java.net import URL
from java.awt import Point

p = Point(12,12)
icon = ImageIcon(URL("http://localhost:8080/gateway/images/Builtin/icons/24/refresh.png")).getImage()
newCursor = Toolkit.getDefaultToolkit().createCustomCursor(icon,p,'TEST')

I prefer the “from module import object” approach too. I was playing with it in the Interactive Script Tester and was just too lazy/tired to refactor it as I would have for production code.

The snippet also has a lot more variables than I would normally use but they helped me break up the code into smaller entities so that I could better determine where exceptions were being generated.

I didn’t mean your code specifically. I could see that it was more verbose for the sake of clarity. I meant just in general, and I was reminded of it since your snippet used the fully qualified name in the code. My guess is that the compiler resolves the pointers at compile time in all cases anyway, and using “from … import …” just reduces the amount of typing while writing the code.

Another quick question- do your pointers look ragged? When I use the same images on buttons, the results are very smooth, but when I assign them to mouse pointers, they are coarse. Does fpmi do some kind of image filtering under the covers when it assigns them to buttons?

edit: I think I see what’s happening. The button scales the image down, and looks smoother that way. It is only noticeable on icons that have curves anyway, and it looks great on the other ones. I’ll look at scaling the image before I assign it to the cursor object if I get an icon that really doesn’t look right.

You might want to take a look at the “getBestCursorSize” entry on Carl’s link above.

It recommends calling “getBestCursorSize” to get the cursor dimensions and selecting a image that is of comparable size. It also notes that rescaling an image can degrade quality.

[color=#FF4000]WARNING.[/color] This is a dangerous, experimental (read: unsupported) feature. If you use this, make sure the code is only executed in the client, not the designer, because these custom cursor’s break window serialization.

Thanks for the help on this Carl. Yeah, you have to tread lightly, but the end effect looks great.

Btw, disregarding customCursors for the moment, I found a nice site that has a lot of open-source icons that will fit nicely with normal buttons, which serialize just fine: Tango

The standard Tango library is pretty nice, and if you drill down into the other links, you’ll also find Frugal .

All of these can be wrapped into commercial projects for free (with proper credit, of course).

Another quick question about “customCursor”. What is the significance of the “name” parameter? The docs say this: “a localized description of the cursor, for Java Accessibility use”. Does that name do anything for me? It doesn’t seem to matter what I enter, plus I reference the cursor like this anyway:

newCursor = Toolkit.getDefaultToolkit().createCustomCursor(icon,p,'View')

Just curious.

Java Accessibility is going to come into play when people with special gui needs (in this case, blindness) use the software. This can help the software dictate to the user that the cursor has changed in a non-visual way.