Search |
||
How to drag nodes and windows?Posted by malenkov on December 24, 2008 at 11:11 AM PST
Every JavaFX node is able to process mouse movement events. Thanks to this ability the user can easily drag nodes on the scene or move windows. However, there are some nuances worth mentioning... It is very easy to create an application that could be dragged when you click on its contents. This feature is important for transparent windows and widgets which have no control elements provided by the window manager. For example, consider the following widget template. var stage: Stage = Stage {
style: StageStyle.TRANSPARENT
scene: Scene {
fill: null
width: ...
height: ...
content: Group {
content: ...
onMouseDragged: function(event) {
stage.x += event.dragX;
stage.y += event.dragY;
}
}
}
}
Now create a simple application with three draggable circles of different colors. Note that the VBox {
translateX: 200
translateY: 70
spacing: 10
content: for (color in colors)
Circle {
var x: Number;
var y: Number;
onMousePressed: function(event) {
x = event.node.translateX;
y = event.node.translateY;
}
onMouseDragged: function(event) {
event.node.translateX = x + event.dragX;
event.node.translateY = y + event.dragY;
}
fill: color
radius: 50
}
}
The example above has several issues. First, if you place two circles so that they overlap each other, you might be able to drag both circles simultaneously. To prevent this sort of behavior, you can set the VBox {
translateX: 200
translateY: 70
spacing: 10
content: for (color in colors)
Circle {
var x: Number;
var y: Number;
onMousePressed: function(event) {
x = event.node.translateX;
y = event.node.translateY;
event.node.toFront();
}
onMouseDragged: function(event) {
event.node.translateX = x + event.dragX;
event.node.translateY = y + event.dragY;
}
blocksMouse: true
fill: color
radius: 50
}
}
One cannot but notice a strange behavior when pressing the mouse on the circle. The fact of the matter is that all nodes in the group are layed out all over again every time when the group content changes. So this approach is not recommended for a group that contains a draggable node and uses a layout mechanism. Even if you write some code that stores the location of the group's objects, the group bounds can be changed. The latter may result in laying out of objects in groups of higher levels. To solve this issue, create another application where draggable nodes belong to the top level group that does not lay out its content. Group {
translateX: 200
translateY: -40
var offset: Number;
content: for (color in colors)
Circle {
var x: Number;
var y: Number;
onMousePressed: function(event) {
x = event.node.translateX;
y = event.node.translateY;
event.node.toFront();
}
onMouseDragged: function(event) {
event.node.translateX = x + event.dragX;
event.node.translateY = y + event.dragY;
}
blocksMouse: true
fill: color
radius: 50
centerY: offset += 110
}
}
To summarize create a new application with the Group {
translateX: 200
translateY: -40
var offset: Number;
content: for (color in colors)
DragDropNode {
node: Circle {
fill: color
radius: 50
centerY: offset += 110
}
}
}
Note that the class DragDropNode extends CustomNode {
var node: Node;
override function create() {
Group {
var x: Number;
var y: Number;
onMousePressed: function(event) {
x = translateX;
y = translateY;
toFront();
effect = Glow {
level: 0.5
}
}
onMouseDragged: function(event) {
translateX = x + event.dragX;
translateY = y + event.dragY;
}
onMouseReleased: function(event) {
effect = null
}
blocksMouse: true
content: bind node
}
}
}
»
Related Topics >>
Programming Comments
Comments are listed in date ascending order (oldest first)
|
||
|
|