This discussion is archived
3 Replies Latest reply: Dec 29, 2012 7:47 AM by 950907 RSS

MouseDrag Entered (reactivate after a children blocked)

950907 Newbie
Currently Being Moderated
Hi smart guys,

I have a new problem I just can solve by some unneccessary events.

If -during a drag - I enter a node (extends VBox) and I then enter one of its children. So the child blocks the "direct Drag". Therefore I would need it to"exit" the "father" node and enter the childnode.

I can workaround, reacting by using onDragged() but these are very much repetitions that are not needed.

So,
can I make Nodes that are blocked by other Nodes reenter and get the OnMouseDragEntered() function again?
(The user can leave both nodes and come back, sure... but ... It feels not organic for the user, and is therefore not worthy to discuss ;-) )

I will check here the first week very frequently and will be grateful for any hint.

Andreas
  • 1. Re: MouseDrag Entered (reactivate after a children blocked)
    950907 Newbie
    Currently Being Moderated
    Hi,

    I got a similar problem with OnMouseClicked().
    If i drag a node from a to b, when both positions are above but not directly at the node. The node will trigger its "clicked" event, since the mouse pressed and the mouse released on the same node.
    I cant consume the mouse pressed event from a child node.
  • 2. Re: MouseDrag Entered (reactivate after a children blocked)
    James_D Guru
    Currently Being Moderated
    [Edited: think I understand what you are asking now.]

    I can think of a couple of ways to do this. The easiest is probably, as you say, to listen for a mouse drag event drag-over, as well as mouse entered and mouse exited. If you use an ObjectProperty<Node> to store the current drop target it's not too messy:
    final ObjectProperty<Node> dropTarget = new SimpleObjectProperty<Node>(null);
    dropTarget.addListener(new ChangeListener<Node>() {
      public void changed(ObservableValue<? extends Node> observable, Node oldValue, Node newValue) {
         if (oldValue != null) {
           // update oldValue as it's no longer the drop target, for example:
           oldValue.getStyleClass().remove("drop-target");
         }
        if (newValue != null) {
          // update newValue as new drop target:
          newValue.getStyleClass().add("drop-target");
        }
      }
    });
    ...
    registerNodeAsDropTarget(node, dropTarget); // call for every node which you want to behave as the drop target
    ...
    private void registerNodeAsDropTarget(final Node node, final ObjectProperty<Node> dropTarget) {
      node.setOnMouseDragReleased(new EventHandler<MouseDragEvent>() {
        @Override
        public void handle(MouseDragEvent event) {
          // process drop as usual
          // ...
          dropTarget.set(null);
        }
      });
    
      node.addEventFilter(MouseDragEvent.MOUSE_DRAG_ENTERED, new EventHandler<MouseDragEvent>() {
        @Override
        public void handle(MouseDragEvent event) {
          dropTarget.set(node);
        }
      });
    
      node.addEventHandler(MouseDragEvent.MOUSE_DRAG_EXITED, new EventHandler<MouseDragEvent>() {
        @Override
        public void handle(MouseDragEvent event) {
          dropTarget.set(null);
        }
      });
    
      node.addEventHandler(MouseDragEvent.MOUSE_DRAG_OVER, new EventHandler<MouseDragEvent>() {
        @Override
        public void handle(MouseDragEvent event) { 
          dropTarget.set(node);
        }
      });
    }
    The change listener should not be fired unless oldValue != newValue, so it doesn't get notified on every mouse drag (in case you're worried about performance).

    The only way I can think to avoid the mouse-drag-over event handler is to keep a stack of nodes. On a mouse drag entered, peek at the stack and if there's anything there, set it as not being the drop target. Then put the current node on the stack and make it the current drop target. On a mouse drag exited, do the reverse; remove the current node from the stack and set it as not being the drop target, peek at the stack and if there's anything still there set it as the new drop target. This again isn't too bad, but seems more complex than the approach above.

    I can't see another way, though that doesn't mean there isn't one.

    (All this code is untested, may have some typos.)

    Edited by: James_D on Dec 18, 2012 5:54 PM
  • 3. Re: MouseDrag Entered (reactivate after a children blocked)
    950907 Newbie
    Currently Being Moderated
    Ok, hi ...

    Took me a while to completly understand and adapt to my architecture. I made some alterations and now it is working quite well :-)

    Thank you a lot. You made my christmas :-D

Legend

  • Correct Answers - 10 points
  • Helpful Answers - 5 points