0

我正在尝试EventHandler<ActionEvent>使用 JavaFX 在 Java 8 中提供一个更简单的版本。

最终版本应该看起来像

package dialogutil;

import org.controlsfx.dialog.Dialog;

import javafx.event.ActionEvent;
import javafx.event.EventHandler;

@FunctionalInterface
public interface Clickable extends EventHandler<ActionEvent> {

    public static Clickable EMPTY = () -> {};

    public void onClick();

    @Override
    public default void handle(ActionEvent event) {
        this.onClick();
        if (event != null && event.getSource() != null) {
            ((Dialog)event.getSource()).hide();
        }
    }
}

有了这个,我试图以更简单的方式创建事件处理程序:它们不将事件作为参数,它们关心隐藏自己。

为了演示,我创建了一个测试套件来重现我遇到的问题:

package test;

import javafx.event.ActionEvent;
import javafx.event.EventHandler;

import org.junit.Test;

public class BastelTest {

    /**
     * Interface Complicated is called with a value.
     */
    @FunctionalInterface
    interface Complicated {
        void complicated(int value);
    }


    /**
     * Interface Simple is called without a value.
     */
    @FunctionalInterface
    interface Simple extends Complicated {
        void simple();
        /**
         * The value given is printed and then the call is deflected to the simple method given.
         */
        @Override
        default void complicated(int value) {
            System.out.println("Swallowing the " + value);
            simple();
        }
    }

    /**
     * This is in order to try the Complicated/Simple interface.
     * The given {@link Complicated} is called with a 42.
     * It can be a {@link Simple} as well; in this case the call is deflected.
     * @param x
     */
    private void callIt(Complicated x) {
        x.complicated(42);
    }

    /**
     * This is the interface I am indeed working on.
     * Here the deflection doesn't work; instead, I get an AbstractMethodError.
     */
    @FunctionalInterface
    public interface Clickable extends EventHandler<ActionEvent> {

        public static Clickable EMPTY = () -> {};

        public void onClick();

        @Override
        public default void handle(ActionEvent event) {
            System.out.println("Simplifying the call:");
            this.onClick();
            System.out.println("Call simplified.");
        }

    }

    private void handle(EventHandler<ActionEvent> x) {
        System.out.println("Handling null event via " + x);
        x.handle(null);
        System.out.println("Handling nonnull event via " + x);
        x.handle(new ActionEvent());
    }


    @Test
    public void testFunc() {
        callIt(x -> System.out.println("Complicated with " + x));
        callIt((Simple) () -> System.out.println("Called simple."));

        Clickable c = () -> System.out.println("Hdl3");
        c.handle(null);

        handle(x -> System.out.println("Hdl1 " + x));
        handle((Clickable)() -> System.out.println("Hdl2"));
        handle(Clickable.EMPTY);
    }
}

在这里,我预计会发生以下情况:

  • 如果我调用callIt()handle()使用处理程序的基本版本,它会照常调用。
  • 如果我用处理程序类的“专门”简化版本来调用它们,我希望它将调用转向我给出的简化版本。

这仅部分有效:

  • 使用Simple/Complicated组合,它可以工作:调用complicated(int)a 的方法Simple打印给定的参数,然后调用该simple()方法,该方法又表示为 lambda。
  • 然而,我所追求的组合是将 an 表示EventHandler<ActionEvent>为一个 lambda(甚至可能是空的),它形成了一个调用 thisClickable的a 。(请不要对名称感到困惑;这是一个非常具有历史意义的界面,我将对其进行改进,但不会完全改变。)在这种情况下,它不起作用。handle()onClick()

这是我得到的堆栈跟踪:

java.lang.AbstractMethodError: Method test/BastelTest$$Lambda$7.handle(Ljavafx/event/Event;)V is abstract
    at test.BastelTest$$Lambda$7/25282035.handle(Unknown Source)
    at test.BastelTest.handle(BastelTest.java:38)
    at test.BastelTest.testFunc(BastelTest.java:69)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at [usual test case stuff...]

为什么它不起作用?

(如果我对情况不够清楚,请告诉我。)

4

1 回答 1

1
于 2016-04-07T17:47:03.030 回答