Determine if an event was consumed in JavaFX

断了今生、忘了曾经 提交于 2021-01-27 06:37:43

问题


I'm trying to do some off-piste stuff with event handling in JavaFX. I need to be able to determine if an event was consumed after I manually fire it.

In the following example a synthetic mouse event is correctly received, however calling consume() does not update the event.

I've debugged this and found JavaFX actually creates a new event instance so the original is unchanged

public class EventManipulation extends Application {

    public static void main(String[] args) {
        launch(args);
    }

    @Override
    public void start(Stage primaryStage) throws Exception {
        Button button = new Button();
        button.setOnMouseDragged(event -> {
            System.out.println("dragged");
            event.consume();
        });
        primaryStage.setScene(new Scene(new HBox(button), 400, 300));
        primaryStage.show();

        MouseEvent event = new MouseEvent(MouseEvent.MOUSE_DRAGGED, 0, 0, 0, 0, MouseButton.PRIMARY, 1, false, false,
                false, false, false, false, false, false, false, false, null);
        Event.fireEvent(button, event);
        System.out.println(event.isConsumed());  // <== prints false
    }
}

I've discovered EventDispatchChain, however I cannot figure out how to get this to work. The button can generate a event dispatch chain but requires one to start off with... The following fails because I don't know how to create an initial tail.

Event result = button.buildEventDispatchChain(null).dispatchEvent(event);
System.out.println(result.isConsumed());

回答1:


The only solution I have for this is to implement the EventDispatchChain interface. A fairly minimal interface is as follows. Unfortunately the built in version used by javafx is in a non-accessible package - com.sun.javafx.event.EventDispatchChainImpl

private class SimpleChain implements EventDispatchChain {

    private Deque<EventDispatcher> dispatchers = new LinkedList<>();

    @Override
    public EventDispatchChain append(EventDispatcher eventDispatcher) {
        dispatchers.addLast(eventDispatcher);
        return this;
    }

    @Override
    public EventDispatchChain prepend(EventDispatcher eventDispatcher) {
        dispatchers.addFirst(eventDispatcher);
        return this;
    }

    @Override
    public Event dispatchEvent(Event event) {
        if (dispatchers.peekFirst() != null) {
            Event result = dispatchers.removeFirst().dispatchEvent(event, this);
            if (result != null) {
                return result;
            } else {
                event.consume();
                return event;
            }
        } else {
            return event;
        }
    }
}

This then produces expected result when used like this

Event result = button.buildEventDispatchChain(new SimpleChain()).dispatchEvent(event);
System.out.println(result.isConsumed());


来源:https://stackoverflow.com/questions/49538364/determine-if-an-event-was-consumed-in-javafx

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!