Some Gotchas for Java Developers Learning JavaFX

In an earlier post, I had attached slides from a presentation on JavaFX that contained some code examples. I discovered that at least one of them, the ball game, stopped working when I switched to JavaFX 1.3.

I would say it is a quite subtle difference.

What happened was that the onKeyPressed and onKeyReleased were not called. My immediate reaction was that it was due to some bug in JavaFX but yesterday I realized what had happened.

In JavaFX 1.3, when you call requestFocus, a method on Node, the node has to be part of a scene. “To be eligible to receive the focus, the node must be part of a scene …”

This worked in JavaFX 1.2:


var field = Rectangle {
onKeyPressed: function ... ... }
field.requestFocus();
Stage {
scene: Scene {
content: [
field,
... }

In JavaFX 1.3 the focus request is denied since the rectangle is not part of Scene, yet. What works now is instead:

var field = …

Stage {

   …

}

field.requestFocus();

The order in which you put things at script level, is important. What I discovered earlier when I held a JavaFX workshop for some very experienced Java developers, is that this was one thing that we do not understand immediately. I do not know why, but the script level concept does not map to anything similar in Java. My approach was to say “think of it as large method”.

The other thing that we, as Java developers, run into is that instantiating objects is not the same as declaring an anonymous type in Java, although it looks like that.

Consider this JavaFX code:

var field = Rectangle { ... onKeyPressed : function(e: KeyEvent): Void { ... } }

and this Java code:

Rectangle field = new Rectangle() {

       ...

     @Override

     void onKeyPressed(KeyEvent e) {

           ...

     }

}

In JavaFX, the property onKeyPressed is assigned a function object while in Java we are overriding the onKeyPressed method. The difference becomes apparent when the key event shall do something with the rectangle object itself.

In JavaFX:

field.x = field.x + 1

In Java

this.setX(this.getX() + 1);

Which brings us to the next thing that I experienced during the workshop. The type inference problem with cyclic references. When you access the rectangle as above, the JavaFX compiler will protest about not coping with the cyclic reference. So you need to declare the type explicitly:

var field: Rectangle = Rectangle …

Not intuitive to me and obviously not to several of the Java programmers in my workshop. I explained it as “the compiler can’t hold its breath for so long”. Which caught on.

Hope this post caught on. If you like to do a workshop and learn JavaFX basics, let me know – it is fun!

2 responses on “Some Gotchas for Java Developers Learning JavaFX

  1. Thank you. It helped me with my project. My node never requested focus in 1.1 version.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.