问题
Moving a node (Label
in this case) within its parent Pane
(lets call it moving), works as expected by adding appropriate handlers for MouseEvent
:
node.setOnMousePressed(new EventHandler<MouseEvent>() {
@Override public void handle(MouseEvent mouseEvent) {
x = node.getLayoutX() - mouseEvent.getSceneX();
y = node.getLayoutY() - mouseEvent.getSceneY();
}
});
node.setOnMouseDragged(new EventHandler<MouseEvent>() {
@Override public void handle(MouseEvent mouseEvent) {
node.setLayoutX(mouseEvent.getSceneX() + x);
node.setLayoutY(mouseEvent.getSceneY() + y);
}
});
Dragging the Label
and dropping it at another Pane
(lets call it dragging) also works as expected by adding appropriate handlers to source :
node.setOnDragDetected(new EventHandler <MouseEvent>() {
@Override public void handle(MouseEvent event) {
Dragboard dragboard = node.startDragAndDrop(TransferMode.COPY_OR_MOVE);
ClipboardContent content = new ClipboardContent();
content.putString(node.getId());
dragboard.setContent(content);
event.consume();
}
});
and target:
target.setOnDragOver(new EventHandler <DragEvent>() {
@Override public void handle(DragEvent event) {
event.acceptTransferModes(TransferMode.COPY_OR_MOVE);
event.consume();
}
});
target.setOnDragDropped(new EventHandler <DragEvent>(){
@Override public void handle(DragEvent event) {
Dragboard dragboard = event.getDragboard();
if (dragboard.hasString()) {
Node dragged = scene.lookup("#"+dragboard.getString());
((Pane) dragged.getParent()).getChildren().remove(dragged);
target.getChildren().add(dragged);
event.setDropCompleted(true);
}
else{
event.setDropCompleted(false);
}
event.consume();
}
});
The problem is getting both work together. After adding drag-drop support it seems that MouseEvent
s are disabled so "moving" does not work.
Sure, I can work-around it and enable drag-drop only when Label
is outside its parent Pane
, but I wonder is this the appropriate way to get both functionalities ?
Here is a mcve. Setting isEnableDargAndDrop
to false
will disable node.setOnDragDetected
thus enable moving it:
import javafx.application.Application;
import javafx.event.EventHandler;
import javafx.scene.Cursor;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.input.ClipboardContent;
import javafx.scene.input.DragEvent;
import javafx.scene.input.Dragboard;
import javafx.scene.input.MouseEvent;
import javafx.scene.input.TransferMode;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.Pane;
import javafx.stage.Stage;
public class DragTest extends Application {
private double x, y;
private boolean isEnableDargAndDrop;
private Scene scene;
@Override public void start(Stage primaryStage) throws Exception {
isEnableDargAndDrop = true;
GridPane root = new GridPane();
Label label = getLabel();
Pane leftPane = getPane(label, "cyan");
root.add(leftPane,0,0);
Pane rightPane = getPane(null, "yellow");
root.add(rightPane,1,0);
scene = new Scene(root);
primaryStage.setScene(scene);
primaryStage.show();
addDragSupport(label);
addDropSupport(rightPane);
addDropSupport(leftPane);
}
private Label getLabel() {
Label label = new Label(" Move me ");
label.setId("label");
label.setStyle("-fx-background-color:white;-fx-border-width: 1;-fx-border-color: red;" );
return label;
}
private Pane getPane(Node label, String color) {
Pane pane = (label == null)? new Pane() : new Pane(label);
pane.setStyle("-fx-background-color:"+color+";");
pane.setPrefSize(150,100);
return pane;
}
private void addDragSupport(Node node) {
node.setOnMousePressed(new EventHandler<MouseEvent>() {
@Override public void handle(MouseEvent mouseEvent) {
x = node.getLayoutX() - mouseEvent.getSceneX();
y = node.getLayoutY() - mouseEvent.getSceneY();
node.setCursor(Cursor.MOVE);
}
});
node.setOnMouseReleased(new EventHandler<MouseEvent>() {
@Override public void handle(MouseEvent mouseEvent) {
node.setCursor(Cursor.HAND);
}
});
node.setOnMouseDragged(new EventHandler<MouseEvent>() {
@Override public void handle(MouseEvent mouseEvent) {
node.setLayoutX(mouseEvent.getSceneX() + x);
node.setLayoutY(mouseEvent.getSceneY() + y);
}
});
node.setOnMouseEntered(new EventHandler<MouseEvent>() {
@Override public void handle(MouseEvent mouseEvent) {
node.setCursor(Cursor.HAND);
}
});
node.setOnDragDetected(new EventHandler <MouseEvent>() {
@Override public void handle(MouseEvent event) {
if(! isEnableDargAndDrop ) { return;}
Dragboard dragboard = node.startDragAndDrop(TransferMode.COPY_OR_MOVE);
ClipboardContent content = new ClipboardContent();
content.putString(node.getId());
dragboard.setContent(content);
event.consume();
}
});
}
private void addDropSupport(Pane target) {
target.setOnDragOver(new EventHandler <DragEvent>() {
@Override public void handle(DragEvent event) {
event.acceptTransferModes(TransferMode.COPY_OR_MOVE);
event.consume();
}
});
target.setOnDragDropped(new EventHandler <DragEvent>(){
@Override public void handle(DragEvent event) {
Dragboard dragboard = event.getDragboard();
if (dragboard.hasString()) {
Node dragged = scene.lookup("#"+dragboard.getString());
if((dragged == null) || (dragged.getParent() == target)) {return;}
((Pane) dragged.getParent()).getChildren().remove(dragged);
target.getChildren().add(dragged);
event.setDropCompleted(true);
}
else{
event.setDropCompleted(false);
}
event.consume();
}
});
}
public static void main (String[] args) {launch(null); }
}
来源:https://stackoverflow.com/questions/44878414/moving-a-node-within-its-parent-pane-and-dropping-it-to-another