java - JavaFx 的 setOnAction 方法在底层是如何工作的?
问题描述
在我的面向对象编程课程中,我们最近的主题是通过 JavaFX 进行事件驱动编程。这些概念相对有趣,尽管有时让我很困惑。我一直在努力理解的一件事是该setOnAction()
方法的工作原理。
正如我的导师所说,这个方法接受一个具有句柄方法的类的对象,并在触发事件时调用该句柄方法。
例如在我们的start
方法中:
class MyHandler implements EventHandler<ActionEvent> {
@Override
public void handle(ActionEvent actionEvent) {
System.out.println("Handled");
}
}
Button button = new Button();
button.setOnAction(new MyHandler());
但是,我无法理解这是如何在幕后工作的。方法究竟是如何setOnAction
“知道”调用对象的句柄方法的MyHandler
?是否可以实现我自己的 a 版本setOnAction
,在其中我调用任何传入对象的特定命名方法?
如果我们根本不实现句柄方法,而是说一个fakeHandle
方法,就像这样。
class MyHandler {
public void fakeHandle(ActionEvent actionEvent) {
System.out.println("Handled");
}
}
Button button = new Button();
button.setOnAction(new MyHandler());
我们的代码还能工作吗?
解决方案
正如我的导师所说,这个方法接受一个具有句柄方法的类的对象,并在触发事件时调用该句柄方法。
I suspect there's a slight misunderstanding or a poor choice of words happening here. You cannot pass any arbitrary object whose class defines a handle(ActionEvent)
method to the setOnAction
method. The setOnAction
method is defined to accept an EventHandler<ActionEvent>
implementation, and it's that interface that defines the handle
method.
This is exactly what interfaces are for. They define a contract that all implementations must follow. It doesn't matter what object you pass to setOnAction
so long as its class implements EventHandler<ActionEvent>
. And that's how JavaFX knows about the handle
method, because it knows about the EventHandler
interface.
Your second code example won't compile because myHandler
doesn't implement EventHandler<ActionEvent>
. But even if it did your fakeHandle
method would not be invoked (by JavaFX code) because JavaFX is not aware of it.
Explaining exactly how the entire event-handling process works under-the-hood in JavaFX is an in-depth process. If you really want to understand this then I suggest reading the code—<a href="https://github.com/openjdk/jfx" rel="nofollow noreferrer">JavaFX is open source. However, if you only want to understand event-handling from a user's perspective (i.e. an API level) then this tutorial should help.
推荐阅读
- mysql - 复杂的删除
- laravel - 重新发送 2Factor Authentication 验证码(Laravel 和 Nexmo)
- java - 如何使用 Java 代码在 Jmeter .jmx 文件中添加正则表达式提取器和 cookie 管理器?
- mysql - 使用 docker-compose,数据库容器未启动并运行
- here-api - 查找航路点附近的高速公路
- tsql - 如何在与 SQL Server 2008 兼容的 SQL Server 2016 中引发错误
- c++ - 无法弄清楚错误来自哪里(调试器说分段错误)
- c++ - 遵循 C++ 中的构造函数执行顺序
- python - 如何使用 python 在子进程中运行或发送 sudo 命令?
- mongodb - 排序时未使用 MongoDB 索引,尽管前缀匹配