带有通用侦听器的 JavaFX 中的 ToggleButtons

ToggleButtons in JavaFX with generic listeners

我有 10 个切换按钮,比如 tb1、tb2、..等等。每一个都附有一个用户数据。我需要附加一个侦听器,以便在单击和取消单击按钮时执行的操作(指令序列)。我希望监听器是通用的(可用于所有按钮)。

我面临的问题是,如何通过此访问 listener.Please 帮助中单击按钮的用户数据。

@FXML
private ToggleButton tb1;
@FXML
private ToggleButton tb2;

String cpuLoad1 ="D:/myWorkspace/TestAttacks/input_folder/app_debug.apk";
String cpuLoad2 = "D:/myWorkspace/TestAttacks/input_folder/cpuLoad1.apk";


public void initialize(){

    tb1.setUserData(cpuLoad1);
    tb2.setUserData(cpuLoad2);

    ChangeListener clt1 = new ChangeListener() {
        public void changed(ObservableValue ov,
                Object toggle, Object new_toggle){
            if(new_toggle.equals(true)){

                /*how can I acces togglebutton userdata here. 
                 *I would like to pass it as arguement to this class object*/
                App load = new App(buttonClicked.getUserData());    //button clicked could tb1 or tb2
                load.installApp();
                load.launchApp();

            }else{
                System.out.println("OFF");
                /*how can I acces togglebutton userdata here. 
                 *I would like to pass it as arguement to this class object.*/
                App load = new App(buttonClicked.getUserData());
                load.unInstallApp();
            }
        }
    };

    tb1.selectedProperty().addListener(clt1);

    tb2.selectedProperty().addListener(clt1);

}

您有多种选择。

Option1:ToggleButton收集到一个集合中,直接在监听器中使用引用:

List<ToggleButton> toggles = new ArrayList<>(Arrays.asList(tb1, tb2));

for(ToggleButton toggle:toggles)
    toggle.selectedProperty().addListener((observable, oldValue, newValue) ->
        System.out.println(toggle.getText() + " - Selected: " + toggle.isSelected() + "; UserData: " + toggle.getUserData()));

选项 2: 您可以使用 onActionProperty:

tb1.setOnAction(e -> {
    ToggleButton toggle = (ToggleButton) e.getSource();
    System.out.println(toggle.getText() + " - Selected: " + toggle.isSelected()
            + "; UserData: " + toggle.getUserData());
});

Option3:如果你需要存储监听器,你可以自己实现ChangeListener.

public class Toggles extends Application {
    public static void main(String[] args) { launch(args); }

    @Override
    public void start(Stage primaryStage) throws Exception {

        VBox vBox = new VBox();
        for (int i = 0; i < 20; i++) {
            ToggleButton tb = new ToggleButton("ToggleButton" + i);
            tb.setUserData("UserData" + i);
            tb.selectedProperty().addListener(new ToggleButtonSourcedChangeListener(tb));
            vBox.getChildren().add(tb);
        }

        Scene scene = new Scene(new BorderPane(vBox), 320, 240);
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    private abstract static class SourcedChangeListener<T extends Node> implements ChangeListener<Boolean> {
        T source;

        SourcedChangeListener(T source) {
            this.source = source;
        }
    }

    private static class ToggleButtonSourcedChangeListener extends SourcedChangeListener<ToggleButton> {

        ToggleButtonSourcedChangeListener(ToggleButton source) {
            super(source);
        }

        @Override
        public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) {
            System.out.println(source.getText() + " - Selected: " + source.isSelected()
                    + "; UserData: " + source.getUserData());
        }
    }
}

在这个 SSCE 中,我创建了一个抽象 SourceChangeListener,可以通过具体实现进行扩展。通用参数 <T extends Node> 背后的意图是避免强制转换。

当您执行此代码并单击切换按钮时,输出将如下所示:

ToggleButton4 - Selected: true; UserData: UserData4
ToggleButton5 - Selected: true; UserData: UserData5
ToggleButton4 - Selected: false; UserData: UserData4
ToggleButton8 - Selected: true; UserData: UserData8
ToggleButton5 - Selected: false; UserData: UserData5
ToggleButton2 - Selected: true; UserData: UserData2

我建议使用 selectedProperty 的选项之一,因为 onActionProperty 只有在按下按钮(通过鼠标、触摸或按键)或以编程方式调用 fire()方法。其他两个选项将始终有效,即使您以编程方式更改选定状态也是如此。