JavaFX 2 event dispatching to underlying nodes

2019-02-24 09:04发布

Is there a correct way to solve the problem with event propagation between two sibling panes?

For example we have StackPane with 2 panes inside.

StackPane p = new StackPane();
Region p1 = new Region();
Region p2 = new Region();
p.getChildren().addAll(p1, p2);

p2 in this example capture mouse events and p1 can't react on it even if event is not consumed.

Is there a correct way to propagate event to p1 if it not consumed by p2?

setMouseTransparent not solve my problem because I need that both children elements react on mouse.

Thanks for advise.

4条回答
仙女界的扛把子
2楼-- · 2019-02-24 09:22

Trying this might also work,

p1.setEventDispatcher(p2.eventDispatcherProperty().get()); 

EventDispatcher Interface

查看更多
【Aperson】
3楼-- · 2019-02-24 09:25

My problem was partially solved. Maybe I not quite correctly formulate question. I write app like graphic-editor and have tools-layer panes on stackpane with guides, grid, selection-tools etc. and need that children of this layers can handle mouse and panes itself will be transparent for mouse events.

Problem was solved by override pickNode, not in public API, but it work. Maybe help somebody.

protected Node impl_pickNodeLocal(double localX, double localY) {
    if (containsBounds(localX, localY)) {
        ObservableList<Node> children = getChildren();
        for (int i = children.size()-1; i >= 0; i--) {
            Node picked = children.get(i).impl_pickNode(localX, localY);
            if (picked != null) return picked;
        }
        // hack to make pane itself transparent for mouse
        // if (contains(localX, localY)) return this;
    }
    return null;
}
查看更多
迷人小祖宗
4楼-- · 2019-02-24 09:26

By default events will just propagate up the heirarchy and terminate at the root. There are a few approaches you could take to solve your problem.

  1. Create your own event instance. Add an event handler to both regions that triggers your shared event instance. Add any event handling code you want to be common across regions to the shared instance. This is the approach I would take from the description you've given.
  2. Catch all events at the root and, instead of just letting them die, create a global event register that everyone can register for.
  3. Create an event handler at the first region and catches events and redispatches them at the second region (using buildEventDispatchChain.dispatchEvent). Then do the same on the other side.
查看更多
爷、活的狠高调
5楼-- · 2019-02-24 09:26

Just catch the event in an event handler and fire it on the other components:

top.addEventHandler(EventType.ROOT, event -> bottom.fireEvent(event));

You can still add mouse listeners on the top components and it works fine. If the bottom component does more fancy stuff with the event, you might need to clone and adjust it. This also works with more than two children.

查看更多
登录 后发表回答