我正在尝试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...]
为什么它不起作用?
(如果我对情况不够清楚,请告诉我。)