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();
Excellent work….I m impressed with your Picture Dragging Example and Ball Shade…example….
Hi Sir , Thanks for your nice job ,Well done . I need one help from you . I need same as you did on picture draggable but I wanted when i click on one picture that picture come up “I mean come first top” . and i don`t want they join together and move . I wanted single chose and other back don`t move . Please help me . on that matter . I need to work with that on some panel or some canvas .
thank you again .
Looking for your reply as soon as possible
with best regard
Ali
Ali jamali, one way to change the order the nodes appears in the scene is changing the order they are in the ‘content’ field of the Stage object.
As a list, you can change it.
Maybe looking at the JavaFX DOC at http://openjfx.java.sun.com/current-build/doc/ to see if there’s a easier way.
Dear Silveria ,
I have set one onMouseClick for my canvas , But I can not make force action happen in first focus canvas. In other world I have 6 canvas . When I want when i click on one page it become my focus page and come first page . but if other canvas be back of that and Mouse x & y be in the same position must select the topper one . But i don`t know how can i do that . I see the Document but it`s too much complicated to understand with out code example . can you suggest me something .
Hello Silveira 🙂
could you tel me how to bind an inserted class property with the new javafx?
i have a code in old javafx :
class A extends CompositeNode
{
attribute x;
}
and i want to add new other classes to it and bind with the attribute..
content:
[
A{
var:me <= the way to accessing the attribute
content:
B{foo:bind me.x}
}
]
I think your code san be more simple right ?
onMousePressed: function(e:MouseEvent):Void {
startX = endX;
startY = endY;
}
onMouseDragged: function(e:MouseEvent):Void {
endX = e.getDragX()+startX;
endY = e.getDragY()+startY;
}
Regards.. 🙂
wildan, yes! Worked here.
Thanks for this advice.
Wildan, no, I noticed now that this doesn’t work properly in the second click.
The correct is the code from the example in the post.
[…] 14 to 42 is the same dragging approach I showed in the post Draggable Nodes, but this time creating a class that inherits the behavior […]
[…] on JavaFX. First I created a movable rectangle using the same idea of draggable nodes I already had posted before. import javafx.input.MouseEvent; import javafx.scene.geometry.Rectangle; public class […]
Hi,
I’ve used your rotating images script to test a container. You can check the result at : http://crowtheries.net/?p=83
UZjw3d hi! nice site!
Good Job Silveira !
mandou bem !!
hi sir, just want to ask co’z im using Jcreator how im going to run the program and i do know what im going to start…. its realy nice i want to do that…
Hey I tried your class Drag Group, I am currently using javaFX ver 1.2 so I converted some of our code. But it doesn’t work, I am putting two normal rectangles instead of circles you put even the Frame doesn’t show up. What may be causing the problem.
P.S
I am trying to make an iphone app where user can scroll the menu by dragging it .
Hello, Jason Allen Drug Bust http://www.aunaturelbaby.com/ – buy cipro Order Cipro (Ciprofloxacin) at discounted price! Generic Cipro (Ciprofloxacin) always in stock! [url=http://www.aunaturelbaby.com/]cheap ciprofloxacin[/url]
[…] GalerÃa de Flickr […]