button.onActionProperty().addListener在javafx中不起作用

1 java events javafx

我是Java的新手,我正在尝试Java事件,但我绝对迷失了.我知道来自C#的事件在哪里没有问题,而且它们完美无缺,但Java是不同的宇宙.我试图在互联网上找到一些东西,但我无法想象它,所以我在这里.

我有一个对象,我需要触发一些动作.触发此操作时,我不仅需要调用一个事件处理程序,还需要调用来自不同对象的更多事件处理程序.

例如,我只是使用Button类.

有两种方法可以做到这一点:

一种方法是使用button.setOnAction方法.但这不起作用,因为当我第二次调用此方法(来自另一个对象)时,我只是将一个事件处理程序替换为另一个.你可以在方法的代码中看到我的意思initEventsUselessWay().

第二种方式是使用button.onActionProperty().addListener.但这根本不起作用.你可以在方法中看到initEventsNeededWay().

那么,为什么button.onActionProperty().addListener不工作?

在Javafx中有什么方法可以做到这一点吗?

最后我不会使用Button类,但像MyClass这样的东西我需要在这里实现它.但是如果这不适用于Button类,那么它也无法在MyClas上运行.

非常感谢您的建议.

package sample;

import javafx.application.Application;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.Pane;
import javafx.stage.Stage;

public class JavaEventsTest1589 extends Application {
private Button btnDemo1;
private Button btnDemo2;

@Override
public void start(Stage primaryStage) {
    // panel
    Pane rootPane = new Pane();

    // scene
    Scene scene = new Scene(rootPane, 300, 250);
    primaryStage.setTitle("events demo");
    primaryStage.setScene(scene);

    // button 1
    btnDemo1 = new Button();
    rootPane.getChildren().add(btnDemo1);
    btnDemo1.setText("Execute Demo 1");
    btnDemo1.setLayoutX(50);
    btnDemo1.setLayoutY(10);

    // button 2
    btnDemo2 = new Button();
    rootPane.getChildren().add(btnDemo2);
    btnDemo2.setText("Execute Demo 2");
    btnDemo2.setLayoutX(50);
    btnDemo2.setLayoutY(50);

    initEventsUselessWay();

    initEventsNeededWay();

    primaryStage.show();
}

public static void main(String[] args) {
    launch(args);
}

private void initEventsUselessWay() {

    btnDemo1.setOnAction(new EventHandler<ActionEvent>() {
        @Override
        public void handle(ActionEvent actionEvent) {
            runDemoPrimaryReaction();
        }
    });

    btnDemo1.setOnAction(new EventHandler<ActionEvent>() {
        @Override
        public void handle(ActionEvent actionEvent) {
            runDemoSecondaryReaction();
        }
    });
}

private void initEventsNeededWay() {

    btnDemo2.onActionProperty().addListener(new ChangeListener<EventHandler<ActionEvent>>() {
        @Override
        public void changed(ObservableValue<? extends EventHandler<ActionEvent>> observableValue, EventHandler<ActionEvent> actionEventEventHandler, EventHandler<ActionEvent> actionEventEventHandler2) {
            runDemoThisINeed_No1();
        }
    });

    btnDemo2.onActionProperty().addListener(new ChangeListener<EventHandler<ActionEvent>>() {
        @Override
        public void changed(ObservableValue<? extends EventHandler<ActionEvent>> observableValue, EventHandler<ActionEvent> actionEventEventHandler, EventHandler<ActionEvent> actionEventEventHandler2) {
            runDemoThisINeed_No2();
        }
    });

}

private void runDemoPrimaryReaction() {
    System.out.println("useless way - primary reaction");
}

private void runDemoSecondaryReaction() {
    System.out.println("useless way - secondary reaction");
}

private void runDemoThisINeed_No1() {
    System.out.println("not working way - No1");
}

private void runDemoThisINeed_No2() {
    System.out.println("not working way - No2");
}

}
Run Code Online (Sandbox Code Playgroud)

Jam*_*s_D 7

使用addEventHandler:

btnDemo1.addEventHandler(ActionEvent.ACTION, new EventHandler<ActionEvent>() {
    @Override
    public void handle(ActionEvent actionEvent) {
        runDemoPrimaryReaction();
    }
});

btnDemo1.addEventHandler(ActionEvent.ACTION, new EventHandler<ActionEvent>() {
    @Override
    public void handle(ActionEvent actionEvent) {
        runDemoSecondaryReaction();
    }
});
Run Code Online (Sandbox Code Playgroud)

我建议使用Java 8,在这种情况下你可以写

btnDemo1.addEventHandler(ActionEvent.ACTION, event -> runDemoPrimaryReaction());
btnDemo1.addEventHandler(ActionEvent.ACTION, event -> runDemoSecondaryReaction());
Run Code Online (Sandbox Code Playgroud)

setOnAction(...)方法是一种"方便"的方法.它的工作方式是Button维护一个ObjectProperty<EventHandler<ActionEvent>>.如果你设置这个属性的值(到一个EventHandler<ActionEvent>),该事件处理程序将自动添加到按钮的事件处理程序.如果你第二次设置它,因为它只是一个属性,它将替换现有的事件处理程序.因此,在只有一个处理程序的情况下,您可以使用它来稍微快一些.(它也适用于FXML.)

onActionProperty().addListener(...)完全是另一回事:它倾听财产本身的变化.因此,如果以这种方式注册侦听器,然后调用setOnAction(...),则在调用时将调用您在属性中注册的侦听器setOnAction(而不是在按下按钮时).

看一下教程,特别是第一节"处理事件"和第二节"使用便利方法".第二部分说明了setOnAction实际执行的时间.