Issue
I've been trying to implement Node dragging in JavaFX and I've come across a problem that seems like it should be relatively easy to solve. I'd guess it has to do with how the JavaFX scene graph updates (or doesn't update) after a window resize.
Anyway, the problem is as follows:
The application starts in a small window with a single node that may be clicked and dragged around the window. This works fine in two cases:
- The Node is clicked and dragged in the window before being resized.
- The Node is clicked and dragged in the window after being resized.
But fails in the third:
- The Node is clicked and dragged both before and after the window is resized (enlarged).
It seems the drag events don't recognize the change in the window bounds. In other words, if I click and drag the node, then enlarge the window. Subsequent clicking and dragging attempts will be restricted to the window's original bounds.
Anyway, what follows is a sample JavaFX application I concocted to demonstrate this problem. It replicates the three test cases I described above.
Thanks.
import javafx.geometry.Point2D;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.input.ClipboardContent;
import javafx.scene.input.DragEvent;
import javafx.scene.input.MouseEvent;
import javafx.scene.input.TransferMode;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.Pane;
import javafx.stage.Stage;
import javafx.application.Application;
import javafx.event.EventHandler;
public class Main extends Application {
private AnchorPane node_root;
private BorderPane mRoot;
@Override
public void start(Stage primaryStage) {
try {
node_root = new AnchorPane();
mRoot = new BorderPane();
Scene scene = new Scene(mRoot,400,400);
primaryStage.setScene(scene);
primaryStage.show();
} catch(Exception e) {
e.printStackTrace();
}
addFileSystemNode ();
mRoot.setOnDragDone (new EventHandler <DragEvent>() {
@Override
public void handle(DragEvent event) {
System.out.println ("Drag done");
event.consume();
}
});
}
public static void main(String[] args) {
launch(args);
}
public final void addFileSystemNode () {
Label node_title = new Label();
node_title.setText("drag me!");
node_root.getChildren().add (node_title);
mRoot.getChildren().add (node_root);
buildNodeDragHandlers();
node_root.setLayoutX(100.0);
node_root.setLayoutY(100.0);
}
public void relocateToPoint (Point2D p) {
Point2D p2 = mRoot.sceneToLocal(p);
node_root.relocate (
(int) (p2.getX()),
(int) (p2.getY())
);
}
public void buildNodeDragHandlers() {
mRoot.setOnDragOver(new EventHandler <DragEvent>() {
//dragover to handle node dragging in the right pane view
@Override
public void handle(DragEvent event) {
System.out.println("parent node drag over" + " " + ((Pane) event.getSource()).getId());
event.acceptTransferModes(TransferMode.ANY);
relocateToPoint(new Point2D( event.getSceneX(), event.getSceneY()));
event.consume();
}
});
mRoot.setOnDragDropped(new EventHandler <DragEvent> () {
@Override
public void handle(DragEvent event) {
System.out.println("node drag dropped");
event.setDropCompleted(true);
event.consume();
}
});
//drag detection for node dragging
node_root.setOnDragDetected( new EventHandler <MouseEvent> () {
@Override
public void handle(MouseEvent event) {
System.out.println("Drag detected");
//begin drag ops
relocateToPoint(new Point2D(event.getSceneX(), event.getSceneY()));
ClipboardContent content = new ClipboardContent();
content.putString("node_drag");
node_root.startDragAndDrop (TransferMode.ANY).setContent(content);
event.consume();
}
});
}
}
Solution
It would appear this is a genuine bug in JavaFX. Submitted a bug report. Currently slated for a fix in JDK 9
https://javafx-jira.kenai.com/browse/RT-39892
Answered By - Joel Graff