2

I am attempting to create a "draggable" histogram UI with JavaFX. I have a ScrollPane containing a GridPane with 1 column and lots of rows. In each row is an HBox containing a label. Every 10 rows, there is also an HBox containing a Line.

I tried to make the HBoxes containing lines draggable by setting onMousePressed, onMouseDragged, and onMouseReleased event handlers (shown below). It works if I drag and release an hbox-line above its starting point - it ends up in whatever grid row I put it in, and I can click and drag it again. However, if I drag and release a line below its starting point, I can't get any more mouseEvents for that hBox. I tried adding log statements everywhere, nothing. I tried setting onMouseOver, it also was not fired.

Why would moving an hbox around the grid like this work for dragging up but not down?

lineContainer.setOnMousePressed(new EventHandler<MouseEvent>() {
    @Override
    public void handle(MouseEvent mouseEvent) {
        EventTarget target = mouseEvent.getTarget();

        lastY = mouseEvent.getSceneY();
    }
});
lineContainer.setOnMouseDragged(new EventHandler<MouseEvent>() {
    @Override
    public void handle(MouseEvent mouseEvent) {
        Node target = (Node) mouseEvent.getTarget();
        HBox hBox = null;
        if (target instanceof HBox) {
            hBox = (HBox) target;
        }
        else if (target instanceof Line) {
            hBox = (HBox) target.getParent();
        }
        else { //should never happen
            log.info("target not hbox or line: " + target.getClass());
        }
        if (mouseEvent.getSceneY() <= (lastY - 15)) {
            int row = GridPane.getRowIndex(hBox);
            GridPane.setRowIndex(hBox, --row);
            lastY = mouseEvent.getSceneY();
            lastRow = row - 1;
        } else if (mouseEvent.getSceneY() >= (lastY + 15)) {
            int row = GridPane.getRowIndex(hBox);
            GridPane.setRowIndex(hBox, ++row);
            lastRow = row - 1;
            lastY = mouseEvent.getSceneY();
        }
    }
});
lineContainer.setOnMouseReleased(new EventHandler<MouseEvent>() {
    @Override
    public void handle(MouseEvent mouseEvent) {
        Node tar = (Node) mouseEvent.getTarget();
        HBox hBox = null;
        if (tar instanceof HBox) {
            hBox = (HBox) tar;
        }
        else if (tar instanceof Line && tar.getParent() instanceof HBox) {
            hBox = (HBox) tar.getParent();
        }
        else { //should never happen
            log.info(mouseEvent.getTarget().getClass().toString());
        }
    }
});

UPDATE: I managed to get it working by creating a new HBox, resetting the onMouse... handlers, and copying its children every time the mouse is released. But I still don't know what was causing the original issue...

ArJay
  • 21
  • 4

1 Answers1

0

The following isn't a direct solution for you, but I wanted to say I have a similar problem and share my observations.

My application allows dragging in both axes (X, Y). All I've been able to figure out that some invisible element is 'obscuring' the MouseEvent hitbox. Testing it using an 'MS minesweeper' approach, shows this interfering area to extend from coords (0,0) of the root to (maxX,maxY) of another Node I have in the scene which is a layer above.

My problem was solved by changing z-order of Parent objects (let's call them layers) containing the Nodes that didn't receive their MouseEvents.

JavaFX MouseEvent doc explains that it is only the top level node which receives the event: https://docs.oracle.com/javafx/2/api/javafx/scene/input/MouseEvent.html

Also look at the pickOnBounds property: JavaFX: How to make a Node partially mouse transparent?

Community
  • 1
  • 1
DailyFrankPeter
  • 382
  • 1
  • 13