Reputation: 3118
Just a quick question which is on my mind right now:
I have a JavaFX application that contains (among others) a ScrollPane and I need to capture the MouseClicked event of that ScrollPane. That itself is actually no problem, except that I only need to handle the event if the event target is an instance of a Rectangle, ToggleButton or a ScrollPaneSkin. That is actually quite easy, too, I know. Right now, I have the following code:
@FXML
void scrollPaneOnMouseClicked(MouseEvent event) {
System.out.println(event.getTarget().getClass().getName());
System.out.println(event.getTarget() instanceof ScrollPaneSkin);
if (event.getTarget() instanceof RoomRectangle || event.getTarget() instanceof ToggleButton || event.getTarget() instanceof ScrollPaneSkin) {
// handle
}
}
except that event.getTarget() instanceof ScrollPaneSkin
says false even if System.out.println(event.getTarget().getClass().getName());
outputs com.sun.javafx.scene.control.skin.ScrollPaneSkin$4
(and the debugger confirms that).
I also tried event.getTarget() instanceof ScrollPaneSkin$4
which resulted in a "cannot find symbol"-error.
What did I miss here?
Upvotes: 1
Views: 695
Reputation: 159546
Update
ScrollPaneSkin is now part of the public JavaFX API in more recent JavaFX versions, however, the rest of this answer regarding naming for the anonymous inner class still applies.
ScrollPaneSkin$4
is likely an instance of name mangling for anonymous inner class created inside the ScrollPaneSkin. This is probably why your code event.getTarget() instanceof ScrollPaneSkin
does not work (because the target is actually the instance of the anonymous inner class rather than a skin itself).
The scope of anonymous classes is confined to their parent class, so the compiler must produce a "qualified" public name for the inner class, to avoid conflict where other classes with the same name (inner or not) exist in the same namespace. Similarly, anonymous classes must have "fake" public names generated for them (as the concept of anonymous classes only exists in the compiler, not the runtime). So, compiling the following java program
public class foo { class bar { public int x; } public void zark () { Object f = new Object () { public String toString() { return "hello"; } }; } }
will produce three .class files:
foo.class
, containing the main (outer) class foofoo$bar.class
, containing the named inner class foo.barfoo$1.class
, containing the anonymous inner class (local to method foo.zark)
As ScrollPaneSkin
is a com.sun
which is not supported public API, writing code based upon it is probably not a good idea as it may be fragile and prone to error due to the internal implementation of ScrollPaneSkin, which could change from Java to version to version. I don't have a further suggestion on how you to accomplish what you wish to accomplish.
Upvotes: 2
Reputation: 3118
Ok, I fixed it by myself. The problem was quite simple and the reason is $4
. As I just found out, the $4
points to an anonymous inner class of ScrollPaneSkin
that obviously cannot be accessed from outside. That means that the target really was not an instance of ScrollPaneSkin
but rather an instance of that inner class. The only workaround is to use event.getTarget.getClass().getName()
and do a String-comparison. (Solution taken from here)
Upvotes: 3