Reputation: 1636
I have a Region called 'R', and a Node called 'N'. N is the only child on R. Consider this behaviour:
I have no problems implementing the behaviour I've just described. I put a MOUSE_PRESSED handler on R that implements step 2. And I put a MOUSE_DRAGGED handler on N that implements step 4. JavaFX automatically directs the MouseEvents to these handlers on R and N for the presses in step 1 and 3 respectively.
The Problem:
I need to do this WITHOUT step 3. That is, the user should not have to press-release-press-drag, but rather should simply press-drag, and N should "jump" to the mouse location on the "press", and then start receiving MOUSE_DRAGGED events immediately.
Unfortunately, this doesn't happen. The release-click that I'm trying to omit seems to be necessary, otherwise the drag events all happen on R instead of N.
I'm thinking the solution will involve redispatching the initial MOUSE_PRESSED, or something along those lines. Does anyone know a way to do this (or a better way to solve my problem?)
Upvotes: 4
Views: 1218
Reputation: 51535
Node has api to mark it as the target of drag gestures:
public void startFullDrag()
Starts a full press-drag-release gesture with this node as gesture source. This method can be called only from a DRAG_DETECTED mouse event handler. More detail about dragging gestures can be found in the overview of MouseEvent and MouseDragEvent.
Assuming circle being your currently active node in a pane (borrowing code/names from James's answer), the collaborators are handlers on
In code:
pane.setOnMousePressed(new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent event) {
circle.setCenterX(event.getX());
circle.setCenterY(event.getY());
}
});
pane.setOnDragDetected(new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent event) {
circle.startFullDrag();
}
});
circle.addEventHandler(MouseDragEvent.ANY, new EventHandler<MouseDragEvent>() {
@Override
public void handle(MouseDragEvent event) {
circle.setCenterX(event.getX());
circle.setCenterY(event.getY());
}
});
Upvotes: 2
Reputation: 209674
I chose the simplest node to work with for this, but I think this would work in general:
import javafx.application.Application;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.stage.Stage;
public class ClickAndDragTest extends Application {
@Override
public void start(Stage primaryStage) {
final Pane pane = new Pane();
final Circle circle = new Circle(100, 100, 50, Color.CORNFLOWERBLUE);
pane.getChildren().add(circle);
pane.setOnMousePressed(new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent event) {
circle.setCenterX(event.getX());
circle.setCenterY(event.getY());
}
});
pane.setOnMouseDragged(new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent event) {
circle.setCenterX(event.getX());
circle.setCenterY(event.getY());
}
});
final Scene scene = new Scene(pane, 400, 400);
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
Upvotes: 2