In JavaFX, you can create an image map in SceneBuilder using an ImageView containing an Image overlaid with one or more Rectangles. The Rectangles are transparent, allowing the image to show, and are the receivers of events.
This screenshot of SceneBuilder shows an ImageView containing a JPEG of a bass guitar neck. A blue Rectangle with partial transparency is dragged onto the screen, positioned and sized to an area of interest.
An ImageView with a Rectangle Overlay |
Events Associated with the Rectangle Hotspot |
Event Handlers
Each Rectangle is attached to 3 mouse event handlers: pressNote (On Mouse Clicked), hoverOverNote (On Mouse Entered), leaveNote (On Mouse Exited). I use the event.getSource() method to retrieve the object that was clicked, entered or exited. For the entered and exited events, I tweak the opacity to give the user a guide as to what he or she is selecting. This is done by adjusting the Opacity property. I could set or re-set the value directly, but I'm providing an animation of the property to make the interaction more modern.
@FXML
public void hoverOverNote(MouseEvent evt) {
FadeTransition ft = new FadeTransition(Duration.millis(200), (Rectangle)evt.getSource());
ft.setFromValue(0.0);
ft.setToValue(0.3);
ft.play();
}
@FXML
public void leaveNote(MouseEvent evt) {
FadeTransition ft = new FadeTransition(Duration.millis(200), (Rectangle)evt.getSource());
ft.setFromValue(0.3);
ft.setToValue(0.0);
ft.play();
}
I'll describe the pressNote() handler in the next section.
Model
An image map is usually backed up with a model. The map translates the graphical object (a JavaFX Rectangle) to something in the application domain. In this case, a Rectangle is translated into a Note object. A Note object contains a set of fields to describe the tone and position in terms of the bass guitar.
The getters, setters, and constructors are omitted for brevity from the Note class.
public class Note {
private Rectangle noteNode;
private String noteValue;
private String enharmonicValue;
private String onString;
}
The Notes are added to a java.util.Map called "noteMap". Although the class itself contains a reference to the noteNode, I use the noteNode (a JavaFX Rectangle object) as the key for a convenient lookup.
The map must be set in the @FXML initialize() method so that the object references for the Rectangles are valid.
private Map<Rectangle, Note> noteMap;
@FXML
public void initialize() {
noteMap = new LinkedHashMap<Rectangle, Note>();
noteMap.put(rect_e_c, new Note(rect_e_c, "C", null, "E"));
}
Finally, the pressNote() method will unpack the selected Rectangle using getSource() and there is an easy lookup for the Note object. The method can continue with the intended processing, say playing a note or recording the selected value.
@FXML
public void pressNote(MouseEvent evt) {
Note n = noteMap.get( evt.getSource() );
if( log.isDebugEnabled() ) {
log.debug("[PRESS NOTE] note=" + n.getNoteValue() + " was pressed");
}
}
SceneBuilder provides a great way to create JavaFX image maps. Simply create JavaFX shape objects (ex, Rectangle) over an ImageView. Once all the objects are defined, select them all and assign event handlers and set the opacity to zero. This beats the old days of the web where an image map required the developer to come up with a list of coordinates through trial-and-error.
No comments:
Post a Comment