JavaFX mouseEvent method getSceneX() stops after holding mouse buttons - javafx

public void setListeners() {
for(Scene s : Org.scenes) {
s.setOnMouseMoved(new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent event) {
mouseX = event.getSceneX();
mouseY= event.getSceneY();
}
});
}
}
this code works well, however whenever mouse1 or mouse2 is held down, the code does not work, and the mouseX and mouseY variables stay at the same value, despite the mouse being moved around. I cannot understand why holding the mouse buttons pause the updating of the variables.

When you press any button on the mouse that's no more considered as mouse move event, instead it becomes a mouse click event and if you hold the mouse button and move the cursor it will be a mouse drag event. So try adding new listeners setOnMouseClicked() or setOnMouseDragged()
s.setOnMouseClicked(new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent event) {
//what you want to do
}
});
s.setOnMouseDragged(new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent event) {
//what you want to do
}
});

Related

Move an ImageView with a drag and drop event

I am trying to create a JavaFX chess board and I encounter a problem with the drag and drop event on a piece.
chess board image
My chess board is composed of Case class extending Label and these Cases can have a Piece as a graphic (this class extends ImageView).
I am trying to make the pieces movable with a drag and drop event (setOnMouseDragged).
I've tried this code without success:
(we have c, a Case and p, a Piece)
c.setOnMousePressed(mouseEvent -> {
p.mouseAnchorX = mouseEvent.getX();
p.mouseAnchorY = mouseEvent.getY();
});
c.setOnMouseDragged(mouseEvent ->{
p.setLayoutX(mouseEvent.getSceneX() - p.mouseAnchorX);
p.setLayoutY(mouseEvent.getSceneY() - p.mouseAnchorY);
/*
p.setX(mouseEvent.getSceneX() - p.mouseAnchorX);
p.setY(mouseEvent.getSceneY() - p.mouseAnchorY);
*/
/*
p.setTranslateX(mouseEvent.getSceneX()/30 - 25.5);
p.setTranslateY(mouseEvent.getSceneY()/30 - 17);
*/
});
Both [setX / setY] and [setLayoutX / setLayoutY] are not moving the piece.
The closest I got was with the setTranslateX and setTranslateY methods : the pieces are moving but not appropriately.
Ideally, I'd like to use the setLayoutX and setLayoutY methods but I don't get why they don't work in my case.
We create a method with the name makeDraggable(), which has a Node as a parameter. In your case, you can use a for-loop to loop through each piece.
In the method, you create a Group which contains the Node. Then you add EventFilters for dragging and pressing. To remember the initial mouse cursor coordinates use DragContext. To disable MouseEvents for the children we need to add the following lines.
// adds EventFilter
wrapGroup.addEventFilter(
// for any MouseEvent
MouseEvent.ANY,
new EventHandler<MouseEvent>() {
public void handle(final MouseEvent mouseEvent) {
if (dragModeActiveProperty.get()) {
// disable mouse events for all children
mouseEvent.consume();
}
}
});
Then you're ready to add the mouse-pressed EventFilter.
// adds EventFilter
wrapGroup.addEventFilter(
// for mouse pressed
MouseEvent.MOUSE_PRESSED,
new EventHandler<MouseEvent>() {
public void handle(final MouseEvent mouseEvent) {
if (dragModeActiveProperty.get()) {
// remember initial mouse cursor coordinates
// and node position
dragContext.mouseAnchorX = mouseEvent.getX();
dragContext.mouseAnchorY = mouseEvent.getY();
dragContext.initialTranslateX =
node.getTranslateX();
dragContext.initialTranslateY =
node.getTranslateY();
}
}
});
Afterwards, we only need to add the drag EventFilter.
// adds EventFilter
wrapGroup.addEventFilter(
// for mouse dragged
MouseEvent.MOUSE_DRAGGED,
new EventHandler<MouseEvent>() {
public void handle(final MouseEvent mouseEvent) {
if (dragModeActiveProperty.get()) {
// shift node from its initial position by delta
// calculated from mouse cursor movement
node.setTranslateX(
dragContext.initialTranslateX
+ mouseEvent.getX()
- dragContext.mouseAnchorX);
node.setTranslateY(
dragContext.initialTranslateY
+ mouseEvent.getY()
- dragContext.mouseAnchorY);
}
}
});
According to Oracles article about Working with Event Filters the full method can look like this:
private Node makeDraggable(final Node node) {
final DragContext dragContext = new DragContext();
final Group wrapGroup = new Group(node);
wrapGroup.addEventFilter(
MouseEvent.ANY,
new EventHandler<MouseEvent>() {
public void handle(final MouseEvent mouseEvent) {
if (dragModeActiveProperty.get()) {
// disable mouse events for all children
mouseEvent.consume();
}
}
});
wrapGroup.addEventFilter(
MouseEvent.MOUSE_PRESSED,
new EventHandler<MouseEvent>() {
public void handle(final MouseEvent mouseEvent) {
if (dragModeActiveProperty.get()) {
// remember initial mouse cursor coordinates
// and node position
dragContext.mouseAnchorX = mouseEvent.getX();
dragContext.mouseAnchorY = mouseEvent.getY();
dragContext.initialTranslateX =
node.getTranslateX();
dragContext.initialTranslateY =
node.getTranslateY();
}
}
});
wrapGroup.addEventFilter(
MouseEvent.MOUSE_DRAGGED,
new EventHandler<MouseEvent>() {
public void handle(final MouseEvent mouseEvent) {
if (dragModeActiveProperty.get()) {
// shift node from its initial position by delta
// calculated from mouse cursor movement
node.setTranslateX(
dragContext.initialTranslateX
+ mouseEvent.getX()
- dragContext.mouseAnchorX);
node.setTranslateY(
dragContext.initialTranslateY
+ mouseEvent.getY()
- dragContext.mouseAnchorY);
}
}
});
return wrapGroup;
}
Similar to your question: Have a look at this stack overflow discussion.

Javafx retrievable drag and drop bug

I am creating a javafx application with a drag and drop feature. I need to be able to drag from one pane and drop to the next pane. After dropping, all dropped nodes need to be accessible. The drag and drop is working smoothly. However, I am having a problem in which not all nodes are accessible after being dropped. I would drag a node and click on it and sometimes it would respond, but sometimes a random node would no longer exhibit capabilities when I clicked on it. There was no noticeable pattern (that I could see) about which nodes stopped working and which always worked. If anyone has any idea as to why this might be a problem or how to fix it, it would be greatly appreciated. I have looked everywhere and found only one similar issue a few years ago but the page with their solution had been removed.
I will briefly explain how I set up my code structure.
The nodes I am dragging extend StackPane and I drag these nodes onto a center Pane from an ImageView in VBox. However, both of these are children of a Main layout that extends BorderPane which I have called MainEntrance.
In my node's class I have onMousePressed and onMouseDragged features as well as onContextMenuRequested features. In the class of the MainEntrance, I have drag features, as well, that handle when an object is first dragged onto the child Pane from the other child VBox.
The following are the relevant classes/methods:
VBox class: (where nodes are dragged from)
ImageView iV= new ImageView(image);
iV.setId("image");
iV.setOnDragDetected(new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent event) {
dragAndDrop(iV, iV.getId(), event);
}
});
I have drag three ImageViews and these ImageViews are children of a VBox.
MainEntrance:
In this class I have a method that registers my drag events to my pane as such:
PView is my class extension of Pane
public void registerOnDragDropped(PView pView){
pView.setOnDragOver(new EventHandler<DragEvent>() {
#Override
public void handle(DragEvent event) {
event.acceptTransferModes(TransferMode.ANY);
System.out.println("drag over registered");
}
});
pView.setOnDragDropped(new EventHandler<DragEvent>() {
#Override
public void handle(DragEvent event) {
Dragboard db = event.getDragboard();
final String id = db.getString();
double mousePosY = event.getY();
double mousePosX = event.getX();
deviceCounter += 1;
pView.createBoardView(id, deviceCounter, mousePosX, mousePosY);
event.setDropCompleted(true);
}
});
pView.setOnDragExited(new EventHandler<DragEvent>() {
#Override
public void handle(DragEvent event) {
event.acceptTransferModes(TransferMode.ANY);
//computerView.setEffect(null);
event.consume();
}
});
}
Note: this method is in my MainEntrance class (BorderPane). In this class is when I initialize all other child nodes of MainEntrance.
Node: (draggable nodes extend StackPane)
my node's handlers are in a method that I called makeDraggable()
public void makeDraggable(Node node) {
this.setOnMousePressed(new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent event) {
node.getScene().setCursor(Cursor.MOVE);
System.out.println("makeDraggable mouse pressed");
}
});
node.setOnMouseReleased(new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent event) {
node.getScene().setCursor(Cursor.DEFAULT);
}
});
node.setOnMouseDragged(new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent event) {
node.setTranslateX(node.getTranslateX() + event.getX() - 35);
node.setTranslateY(node.getTranslateY() + event.getY() - 35);
event.consume();
node.toFront();
}
});
}
If any other information is needed please let me know. Thank you in advance!
I have figured out the solution to this problem.
The problem was in the rendering order of an attachment I had placed on the node. So when I drag the node on to the screen, I have another node (a line placed on a Pane) that binds the center of the screen to the node. I did not initially think that this was the problem, so I did not even include that class or snippet. However, after playing around with it I realized that this indeed was the problem. I had to add the line to the top of the rendering order. This can be done in the following way in whatever method allows you to create a new node:
Pane line = new Pane();
//add whatever code binds your line to desired places
getChildren.add(0, line);
//add the other node as child

JavaFX opposite function of .requestFocus()?

I'm looking for function in JavaFX, where I can "disable or dismiss" the requested focus.
Here is a screenshot of my program: Screenshot
Every cell is filled with an Eventhandler (onMouseEntered and onMouseExited) and in every onMouseEntered function I have to request the focus like this:
label.requestFocus(). I need to do that, because I'm using KeyEvents to change the content of the cell.
It works fine, but there is a bug: When I move out of the scrollPane, there is still the requested focus on the last entered cell.
How can I solve that issue, without requesting focus for everything around the Scrollpane to fix this bug? Is there a function, where I can dismiss the requested focus, so after exiting a cell, it'll dismiss the focus.
Best regards,
My code:
arbeitetLabel.setOnMouseEntered(new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent mouseEvent) {
arbeitetLabel.requestFocus();
arbeitetLabel.setOnKeyPressed(new EventHandler<KeyEvent>() {
#Override
public void handle(KeyEvent keyEvent) {
// Do some keyEvent Stuff
}
});
}
});
arbeitetLabel.setOnMouseExited(new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent mouseEvent) {
// Dismiss the requested Focus here?
}
});
I'm passing the focus to the parent, that's it!
arbeitetLabel.getParent().requestFocus()

How disable handling mouse events on content area in jfxtras window?

I can drag jfxtras Window by clicking on ImageView in window area. I need to handle mouse move, swipe... events by ImageView. How disable handling mouse events on content window area?
Note: You can drag window by ImageView in content area, but can't by Button.
I found solution. But it seems like hack:
imageView.addEventHandler(MouseEvent.MOUSE_DRAGGED, new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent mouseEvent) {
window.setMovable(false)
}
});
imageView.addEventHandler(MouseEvent.MOUSE_EXITED, new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent mouseEvent) {
window.setMovable(true);
}
});

TextArea does not handle MouseEvent.MOUSE_PRESSED

I am building a JavaFX application and I have a TextArea inserted.
The TextArea has a CSS class assigned (don't know if it matters):
.default-cursor{
-fx-background-color:#EEEEEE;
-fx-cursor:default;
}
There are 2 issues about this TextArea:
-fx-cursor:default; Has no effect as the cursor remains the text cursor. That is weird as i use the same class for a TextField with proper/expected results
The TextArea does not handle MOUSE_PRESSED eventMy code is :
textArea.addEventHandler(MouseEvent.MOUSE_PRESSED, new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent event) {
System.out.println("print message");
}
});
Any ideas why?
I want to note that when I changed EventHandler to handle MOUSE_CLICKED everything is fine
I suspect the default handlers for mouse events on the TextArea are consuming the mouse pressed event before it gets to your handler.
Install an EventFilter instead:
textArea.addEventFilter(MouseEvent.MOUSE_PRESSED, new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent event) {
System.out.println("mouse pressed");
}
});
The Event filter will get processed before the default handlers see the event.
For your css issue, try
.default-cursor .content {
-fx-cursor: default ;
}

Resources