Reputation: 595
I'm trying to do the following in JavaFX. I am using Canvas to draw stuff on the screen and I want the following to happen:
When I click on the Canvas surface (like fast press and release): something happens
When I drag on the Canvas surface (like press and move, then release): something ELSE happens
BUT I want it to exclude the click action if I drag, so if I drag, what would have happened if I clicked should not happen. Sadly, it seems like when I release the mouse, both release and click events launch, even if I drag.
Upvotes: 0
Views: 1280
Reputation: 96
It's a bit late, but in case someone will come here for a solution. I've created a simple class to handle it.
Usage:
clickNotDragDetectingOn(yourNode)
.withPressedDurationTreshold(150)
.setOnMouseClickedNotDragged((mouseEvent) -> {
// logic here
});
Code:
class MouseClickNotDragDetector {
private final Node node;
private Consumer<MouseEvent> onClickedNotDragged;
private boolean wasDragged;
private long timePressed;
private long timeReleased;
private long pressedDurationTreshold;
private MouseClickNotDragDetector(Node node) {
this.node = node;
node.addEventHandler(MOUSE_PRESSED, (mouseEvent) -> {
this.timePressed = currentTimeMillis();
});
node.addEventHandler(MOUSE_DRAGGED, (mouseEvent) -> {
this.wasDragged = true;
});
node.addEventHandler(MOUSE_RELEASED, (mouseEvent) -> {
this.timeReleased = currentTimeMillis();
this.fireEventIfWasClickedNotDragged(mouseEvent);
this.clear();
});
this.pressedDurationTreshold = 200;
}
static MouseClickNotDragDetector clickNotDragDetectingOn(Node node) {
return new MouseClickNotDragDetector(node);
}
MouseClickNotDragDetector withPressedDurationTreshold(long durationTreshold) {
this.pressedDurationTreshold = durationTreshold;
return this;
}
MouseClickNotDragDetector setOnMouseClickedNotDragged(Consumer<MouseEvent> onClickedNotDragged) {
this.onClickedNotDragged = onClickedNotDragged;
return this;
}
private void clear() {
this.wasDragged = false;
this.timePressed = 0;
this.timeReleased = 0;
}
private void fireEventIfWasClickedNotDragged(MouseEvent mouseEvent) {
if ( this.wasDragged ) {
debug("[CLICK-NOT-DRAG] dragged!");
return;
}
if ( this.mousePressedDuration() > this.pressedDurationTreshold ) {
debug("[CLICK-NOT-DRAG] pressed too long, not a click!");
return;
}
debug("[CLICK-NOT-DRAG] click!");
this.onClickedNotDragged.accept(mouseEvent);
}
private long mousePressedDuration() {
return this.timeReleased - this.timePressed;
}
}
Upvotes: 1
Reputation: 595
@wcomnisky
Thank you very much for your help. What I did in the end (I tried using isStillSincePress() in the release event handler and it seemed it was still treating short distance drags as clicks.. though I may have done something wrong) was this: in the mouse press handler I record press coordinates (maybe this idea is similar to the isStillSincePressed() method.. it may have been suggested by its name / description) pressX = event.getX(); pressY = event.getY()
and in the mouse release handler I do this: if( (pressX == event.getX() ) && (pressY == event.getY()) ) doClickAction(); else doDragEndAction()
. Seems to be workin.. for handling actions while dragging, I'll try using the usual drag handler.
Upvotes: 1
Reputation: 406
The method isStillSincePress()
can be used together with the getEventType()
, both from the MouseEvent
API.
Maybe you'll need to implement a threshold for the mouse movement between the MOUSE_PRESSED
and MOUSE_RELEASED
to improve the usability.
Upvotes: 3