如何正确设置自定义事件

好的 - 我已经为此奋斗了很久,阅读了一百万篇文章、教程等。它们似乎都没有直接解决我在这里想做的事情。我有这个小代码示例来说明。


基本上,我希望能够从按钮引发/触发自定义事件并让标签响应该事件。


(请注意,除了我在这里尝试使用实际的 Event 对象之外,我没有兴趣寻找其他方法来做到这一点。我非常清楚如何使用更改侦听器等来做到这一点,但我想学习如何这样做。)


这是代码,您可以看到它没有得到我正在寻找的结果。其中大部分来自一些示例(对我来说并没有真正起作用),我承认这里有些部分让我“呼呼”。


如果有人可以帮助我让它工作,我可以稍后对其进行剖析以确保我了解到底发生了什么。这是代码:


import javafx.application.Application;

import javafx.beans.property.ObjectProperty;

import javafx.beans.property.SimpleObjectProperty;

import javafx.event.Event;

import javafx.event.EventHandler;

import javafx.event.EventType;

import javafx.geometry.Insets;

import javafx.geometry.Pos;

import javafx.scene.Scene;

import javafx.sene.control.Button;

import javafx.scene.control.Label;

import javafx.scene.layout.VBox;

import javafx.stage.Stage;


//-------------------------------------------------------------------

public class MyDemo extends Application {


    public static void main(String[] args) {

    launch(args);

    }


    @Override

    public void start(Stage primaryStage) {


    // label that should receive the event and react to it

    MyLabel lblReceiver = new MyLabel("And I Should Receive & React");


    // button to firs the event

    Button btnSender = new Button("Initate Event");

    btnSender.setPrefWidth(200);

    btnSender.setOnAction(e -> {

        MyEvent.fireEvent(lblReceiver, e); // really confused what the first parameter here is supposed to be.

    });


    // set up stage and show it

    Stage stage = new Stage();

    VBox root = new VBox(btnSender, lblReceiver);

    root.setSpacing(10);

    root.setPadding(new Insets(10, 10, 10, 10));

    Scene scene = new Scene(root);

    stage.setScene(scene);

    stage.show();

    }


}



茅侃侃
浏览 95回答 1
1回答

翻翻过去那场雪

回答除了两个问题外,您似乎已正确设置所有内容。你永远不会添加一个EventHandler监听你的事件的。实现任意接口不会使您的对象对您的自定义事件做出反应。事件处理系统不知道你的接口,甚至不知道你已经实现了它。如果您希望onMyEvent()在事件到达标签时调用您的方法,则需要执行以下操作:public MyLabel() {    //...    addEventHandler(MyEvent.MY_EVENT, event -> onMyEvent());}请注意,我使用addEventHandler的是类本身不依赖于该onMyEvent属性。如果您依赖该属性,则外部代码可能会通过替换EventHandler.这让我想知道MyEventListener接口是否真的有必要。你不能在里面做你需要的EventHandler吗?您实际上从未触发过您的MyEvent.您目前拥有:btnSender.setOnAction(e -> MyEvent.fireEvent(lblReceiver, e));这只是将e(an ActionEvent) 重新点燃到lblReceiver. 该fireEvent方法是由static声明的方法javafx.event.Event。为方法调用加上前缀MyEvent不会改变此处实际调用的方法。将其更改为以下内容:btnSender.setOnAction(e -> Event.fireEvent(lblReceiver, new MyEvent()));// or...btnSender.setOnAction(e -> lblReceiver.fireEvent(new MyEvent()));// The second option is a convenience method and simply forwards to Event.fireEvent为了在您的标签上实际触发您自己的事件类的实例。事件派发基础JavaFX 中的事件处理有两个阶段:捕获阶段第一阶段。在这里,事件从其路径的起点向下传播到目标。在此过程中的每一步,都会调用适当的事件过滤器。过滤器是通过诸如Node.addEventFilter(EventType,EventHandler).冒泡阶段第二阶段。在这里,事件从目标返回到路径的起点。在此过程中的每一步,都会调用适当的事件处理程序。处理程序是通过诸如 和 之类的方法和Node.addEventHandler(EventType,EventHandler)属性添加的。Node.onKeyPressedButtonBase.onAction事件处理由以下组件组成:javafx.event.Event(和子类)实际对象传递过来。携带与事件相关的信息(例如MouseEvents 的光标位置)。一个Event也携带来源。但是,来源是动态的;它始终是EventHandler当前处理事件的对象。因此,EventHandler添加到 a的事件Button将具有Button作为事件源的事件,但同一事件将具有父级作为EventHandler添加到父级的源。即使您EventHandler两次使用同一个实例,此行为也不会改变。javafx.event.EventType细化一类的含义Event。例如,MouseEvent带有MOUSE_PRESSED类型的 a 毫不奇怪地表示鼠标被按下了。一个EventType有一个超类型;这为每种事件形成了所有类型的层次结构。为超类型注册的处理程序也将收到子类型的通知。不能有两个或多个EventType具有相同超类型和名称的 s。这就是为什么实例通常public static final是相应事件类的字段。javafx.event.EventHandler处理其注册的任何事件。这是一个功能接口(可以是 lambda 表达式或方法引用的目标)。执行应用程序级工作的是此接口的实现(即,在触发按钮时执行某些操作)。javafx.event.EventDispatcher负责将事件分派给适当的处理程序。每个能够成为事件目标的对象通常都有自己的调度程序。例如,每个Window、Scene和Nodeinstance 都有自己的EventDispatcher实例(保存在属性中)。注意:在高度专业化的情况之外,您永远不必直接处理此接口。javafx.event.EventDispatchChain表示事件在目标处触发时将采用的路径。此接口的实例用作EventDispatchers 的堆栈。触发事件时,将根据事件的目标创建和配置新链。在场景图和目标是 a 的情况下Node,堆栈由EventDispatcher属于 s的 s 组成Window,Scene然后每个Node向下到(父到子)并包括目标。事件沿这条链向下传播(捕获阶段),然后返回这条链(冒泡阶段)。注意:您可能永远不需要直接使用此界面。javafx.event.EventTarget事件的实际目标。该EventTarget接口具有一种用于构建EventDispatchChain. 换句话说,目标决定了事件的路径。这是中的第一个参数Event.fireEvent(EventTarget,Event)。注意:如果您正在创建一个可以(显然)成为事件目标的对象(并且您的对象不是从 的实现扩展的EventTarget),则只需要使用此接口。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Java