JavaFX.在自定义类中注册事件处理程序



我尝试在我的自定义类中注册eventHandler。我不知道我必须实现什么接口或方法才能在我的自定义类中使用addEventHandler方法。出于这个原因,我的Model类扩展Rectangle(Rectangle类具有addEventHandler机制(。

我也不知道为什么分配的源对象不起作用(请参阅类Controller中的评论(。

创建我通过本教程创建的自定义事件:https://stackoverflow.com/a/27423430/3102393。


项目结构

控制器

package sample;
import javafx.event.Event;
public class Controller {
    private Model model;
    public Controller() {
        model = new Model();
        model.addEventHandler(MyEvent.ROOT_EVENT, this::handler);
    }
    private void handler(MyEvent event) {
        if(event.getEventType().equals(MyEvent.INSTANCE_CREATED)) {
            // Why is event.getSource() instence of Rectangle and not instance of assigned MyObject?
            Object obj = event.getSource();
            System.out.println(event.getMyObject().getText());
        }
    }
    public void clickedCreate(Event event) {
        model.makeEvent();
    }
}

package sample;
import javafx.scene.shape.Rectangle;
import java.util.ArrayList;
public class Model extends Rectangle {
    private ArrayList<MyObject> objects = new ArrayList<>();
    private Integer counter = 0;
    public void makeEvent() {
        MyObject object = new MyObject((++counter).toString() + "!");
        objects.add(object);
        fireEvent(new MyEvent(object, null, MyEvent.INSTANCE_CREATED));
    }
}

自定义事件我的事件

package sample;
import javafx.event.Event;
import javafx.event.EventTarget;
import javafx.event.EventType;
public class MyEvent extends Event {
    public static final EventType<MyEvent> ROOT_EVENT = new EventType<>(Event.ANY, "ROOT_EVENT");
    public static final EventType<MyEvent> INSTANCE_CREATED = new EventType<>(ROOT_EVENT, "INSTANCE_CREATED ");
    public static final EventType<MyEvent> INSTANCE_DELETED = new EventType<>(ROOT_EVENT, "INSTANCE_DELETED");
    private MyObject object;
    public MyEvent(MyObject source, EventTarget target, EventType<MyEvent> eventType) {
        super(source, target, eventType);
        object = source;
    }
    public MyObject getMyObject() {
        return object;
    }
}

最后是我的对象

package sample;
public class MyObject {
    private String text;
    MyObject(String text) {
        this.text = text;
    }
    public String getText() {
        return text;
    }
}

注意(和问题(:我也尝试使用MyObject实例的ObservableList,但我认为没有更新实例属性的通知。

事件基础知识

Event s 使用 Event.fireEvent 触发,该 分 2 步工作:

  1. 使用 EventTarget.buildEventDispatchChain 构建EventDispatchChain
  2. Event传递给生成的EventDispatchChain中的第一个EventDispatcher

此代码片段演示了以下行为:

EventTarget target = new EventTarget() {
    @Override
    public EventDispatchChain buildEventDispatchChain(EventDispatchChain tail) {
        return tail.append(new EventDispatcher() {
            @Override
            public Event dispatchEvent(Event event, EventDispatchChain tail) {
                System.out.println("Dispatch 1");
                tail.dispatchEvent(event);
                return event;
            }
        }).append(new EventDispatcher() {
            @Override
            public Event dispatchEvent(Event event, EventDispatchChain tail) {
                System.out.println("Dispatch 2");
                tail.dispatchEvent(event);
                return event;
            }
        });
    }
};
Event.fireEvent(target, new Event(EventType.ROOT));

它打印

Dispatch 1
Dispatch 2

如您所见,EventTarget构建EventDispatchChain的方式完全取决于EventTarget

这就解释了为什么你必须自己实现addEventHandler等等。

它是如何为Node完成的

这在 Oracle 网站上的 JavaFX:处理事件 - 1 处理事件一文中有详细说明。

重要的细节是:

  • 在事件处理期间使用不同的source对象。
  • EventHandler s/EventFilter s 在事件调度期间使用 (2.(。

这就解释了为什么source值是意外的。

如何实现addEventHandler

如果你

省略了事件捕获和冒泡,做到这一点并不难。您只需要将EventHandler按类型存储在Map<EventType, Collection>>中,并为EventType层次结构中的每个类型调用EventHandler s:

public class EventHandlerTarget implements EventTarget {
    private final Map<EventType, Collection<EventHandler>> handlers = new HashMap<>();
    
    public final <T extends Event> void addEventHandler(EventType<T> eventType, EventHandler<? super T> eventHandler) {
        handlers.computeIfAbsent(eventType, (k) -> new ArrayList<>())
                .add(eventHandler);
    }
    public final <T extends Event> void removeEventHandler(EventType<T> eventType, EventHandler<? super T> eventHandler) {
        handlers.computeIfPresent(eventType, (k, v) -> {
            v.remove(eventHandler);
            return v.isEmpty() ? null : v;
        });
    }
    
    @Override
    public final EventDispatchChain buildEventDispatchChain(EventDispatchChain tail) {
        return tail.prepend(this::dispatchEvent);
    }
    private void handleEvent(Event event, Collection<EventHandler> handlers) {
        if (handlers != null) {
            handlers.forEach(handler -> handler.handle(event));
        }
    }
    private Event dispatchEvent(Event event, EventDispatchChain tail) {
        // go through type hierarchy and trigger all handlers
        EventType type = event.getEventType();
        while (type != Event.ANY) {
            handleEvent(event, handlers.get(type));
            type = type.getSuperType();
        }
        handleEvent(event, handlers.get(Event.ANY));
        return event;
    }
    public void fireEvent(Event event) {
        Event.fireEvent(this, event);
    }
}

相关内容

  • 没有找到相关文章

最新更新