JavaFX的。在自定义类

时间:2016-04-01 13:40:36

标签: events javafx event-handling

我尝试在自定义类中注册eventHandler。我不知道在自定义类中使用addEventHandler方法需要实现哪些接口或方法。出于这个原因,我的Model类扩展了RectangleRectangle类具有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));
    }
}

自定义事件 MyEvent

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;
    }
}

最后是MyObject

package sample;

public class MyObject {
    private String text;

    MyObject(String text) {
        this.text = text;
    }

    public String getText() {
        return text;
    }
}

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

1 个答案:

答案 0 :(得分:5)

活动基础

Event是使用Event.fireEvent解雇的,分为两步:

  1. 使用EventTarget.buildEventDispatchChain构建EventDispatchChain
  2. Event传递给结果EventDispatchChain中的第一个EventDispatcher
  3. 此代码段演示了行为:

    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 s

    是如何完成的

    Oracle网站上的文章JavaFX: Handling Events - 1 Processing Events对此进行了详细介绍。

    重要的细节是:

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

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

    如何实施addEventHandler

    如果你忽略事件捕获和冒泡,那就不难做到这一点。您只需要在EventHandler中按类型存储Map<EventType, Collection>>,并为EventHandler层次结构中的每种类型调用EventType

    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);
        }
    
    }