One thing that I like a lot to do with JavaFX is draggable objects. Due to some recent changes in the JavaFX syntax my old codes for that are no longer working. Joshua Marinacci from Sun’s JavaFX engineering team and other guys from the JavaFX community gave me some tips. Here some strategies I’m using for making draggable nodes in JavaFX.
In this first example, a simple draggable ellipse.
video url: http://www.youtube.com/watch?v=pAJHH-mPLaQ
import javafx.application.*; import javafx.scene.paint.*; import javafx.scene.geometry.*; import javafx.input.*; Frame { width: 300, height: 300, visible: true stage: Stage { content: [ Ellipse { var endX = 0.0; var endY = 0.0 var startX = 0.0; var startY = 0.0 centerX: 150, centerY: 150 radiusX: 80, radiusY: 40 fill: Color.ORANGE translateX: bind endX translateY: bind endY onMousePressed: function(e:MouseEvent):Void { startX = e.getDragX()-endX; startY = e.getDragY()-endY; } onMouseDragged: function(e:MouseEvent):Void { endX = e.getDragX()-startX; endY = e.getDragY()-startY; } } ] } } |
When you need to create a group of draggable objects, you can try thie approach of a draggable group like this. Inside on it, you can put whatever you want.
Video url: http://www.youtube.com/watch?v=mHOcPRrgQCQ
import javafx.application.*; import javafx.scene.paint.*; import javafx.scene.geometry.*; import javafx.input.*; import javafx.scene.*; import javafx.scene.effect.*; import javafx.scene.image.*; import javafx.animation.*; // a graggable group public class DragGroup extends CustomNode{ public attribute content: Node[]; private attribute endX = 0.0; private attribute endY = 0.0; private attribute startX = 0.0; private attribute startY = 0.0; public function create(): Node { return Group{ translateX: bind endX translateY: bind endY content: bind content } } override attribute onMousePressed = function(e:MouseEvent):Void { startX = e.getDragX()-endX; startY = e.getDragY()-endY; } override attribute onMouseDragged = function(e:MouseEvent):Void { endX = e.getDragX()-startX; endY = e.getDragY()-startY; } } // angle animation, cycles between 0 to 360 in 36 seconds var angle = 0.0; var angleAnimation = Timeline { repeatCount: Timeline.INDEFINITE keyFrames : [ KeyFrame { time: 0s values: angle => 0.0 }, KeyFrame{ time: 36s values : angle => 360.0 tween Interpolator.LINEAR } ] } // some pictures from my Flickr albums var me = "http://farm4.static.flickr.com/3042/2746737338_aa3041f283_m.jpg"; var dog = "http://farm4.static.flickr.com/3184/2717290793_ec14c26a85_m.jpg"; var plant = "http://farm4.static.flickr.com/3014/2731177705_bed6d6b8fa_m.jpg"; var bird = "http://farm4.static.flickr.com/3190/2734919599_a0110e7ce0_m.jpg"; var me_89 = "http://farm3.static.flickr.com/2138/2308085138_7b296cc5d0_m.jpg"; Frame { width: 640, height: 480, visible: true stage: Stage { fill: Color.BLACK content: [ DragGroup{ content: ImageView { anchorX: 120, anchorY: 90 rotate: bind 30 + angle image: Image { backgroundLoading: true, url: me } } }, DragGroup { translateX: 300, translateY: 50 content: ImageView { anchorX: 120, anchorY: 90 rotate: bind -30 + angle image: Image { backgroundLoading: true, url: dog } } }, DragGroup { translateX: 300, translateY: 300 content: ImageView { anchorX: 120, anchorY: 90 rotate: bind 90 + angle image: Image { backgroundLoading: true, url: plant } } }, DragGroup { translateX: 200 translateY: 200 content: ImageView { anchorX: 120, anchorY: 90 rotate: bind 90 + angle image: Image { backgroundLoading: true, url: bird } } }, DragGroup { translateX: 30 translateY: 200 content: ImageView { anchorX: 85, anchorY: 120 rotate: bind angle + 180 image: Image { backgroundLoading: true, url: me_89 } } }, ] } closeAction: function() { java.lang.System.exit( 0 ); } } angleAnimation.start(); |
One more example, using the same class DragGroup, we can put multiple nodes using lists.
Video url: http://www.youtube.com/watch?v=gJqy7EdtEqs
import javafx.application.*; import javafx.scene.*; import javafx.scene.geometry.*; import javafx.scene.paint.*; import javafx.input.*; import javafx.animation.*; import java.lang.Math; // Class to create a draggable group of objects public class DragGroup extends CustomNode{ public attribute content: Node[]; private attribute endX = 0.0; private attribute endY = 0.0; private attribute startX = 0.0; private attribute startY = 0.0; override attribute onMousePressed = function(e:MouseEvent):Void { startX = e.getDragX()-endX; startY = e.getDragY()-endY; } override attribute onMouseDragged = function(e:MouseEvent):Void { endX = e.getDragX()-startX; endY = e.getDragY()-startY; } public function create(): Node { return Group{ translateX: bind endX translateY: bind endY content: bind content } } } // angle animation, cycles between 0 to 360 in 10 seconds var angle = 0.0; var angleAnimation = Timeline { repeatCount: Timeline.INDEFINITE keyFrames : [ KeyFrame { time: 0s values: angle => 0.0 }, KeyFrame{ time: 10s values : angle => 360.0 tween Interpolator.LINEAR } ] } // breath animation, go and back from 0.0 to 10.0 in 2 seconds var breath = 0.0; var breathAnimation = Timeline { repeatCount: Timeline.INDEFINITE autoReverse: true keyFrames : [ KeyFrame { time: 0s values: breath => 0.0 }, KeyFrame{ time: 1s values : breath => 10.0 tween Interpolator.LINEAR } ] } // Creates n multi colored floating circles around a bigger circle var n = 12; var colors = [ Color.BLUE, Color.AQUA, Color.MAGENTA, Color.RED, Color.YELLOW, Color.ORANGE, Color.HOTPINK, Color.LIME ]; var chosen = Color.YELLOW; var floatingCircles = Group{ rotate: bind angle content: for (i in [1..n]) Circle { fill: colors[i mod sizeof colors] radius: 10 centerX: Math.cos(i * 2 * Math.PI/n) * 70 centerY: Math.sin(i * 2 * Math.PI/n) * 70 onMouseClicked: function( e: MouseEvent ):Void { chosen = colors[i mod sizeof colors]; } } } var circle = Circle{ radius: bind 50 + breath fill: bind chosen } Frame { width: 400, height: 400, visible: true stage: Stage { fill: Color.BLACK content: [ DragGroup{ translateX: 200, translateY: 200 content: [circle, floatingCircles] } ] } closeAction: function() { java.lang.System.exit( 0 ); } } // starts all animations angleAnimation.start(); breathAnimation.start(); |