简体   繁体   English

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

[英]ToggleButtons in JavaFX with generic listeners

I have 10 toggle buttons say tb1, tb2,.. and so on.我有 10 个切换按钮,比如 tb1、tb2、.. 等等。 Each one has one user data attached to it.每一个都附有一个用户数据。 I need to attach a listener for a action (sequence of instructions) to be performed when button are clicked and unclicked.我需要为单击和取消单击按钮时要执行的操作(指令序列)附加一个侦听器。 I would prefer the listener to be generic (usable for all the buttons).我希望监听器是通用的(可用于所有按钮)。

The problem I am facing is that, how can I access the user data of clicked button in the listener.Please help through this.我面临的问题是,如何访问监听器中单击按钮的用户数据。请帮忙解决这个问题。

@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 argument 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 argument to this class object.*/
                App load = new App(buttonClicked.getUserData());
                load.unInstallApp();
            }
        }
    };
    
    tb1.selectedProperty().addListener(clt1);

    tb2.selectedProperty().addListener(clt1);
    
}

You have several options.您有多种选择。

Option1: Collect the ToggleButton s into a collection and use the reference directly in the listener:选项 1: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()));

Option2: You can use the onActionProperty :选项 2:您可以使用onActionProperty

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

Option3: If you need to store the listeners, you can implement you own ChangeListener .选项 3:如果您需要存储侦听器,您可以实现自己的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());
        }
    }
}

In this SSCE I created an abstract SourceChangeListener that can be extended by concrete implementations.在此 SSCE 中,我创建了一个抽象的SourceChangeListener ,它可以通过具体实现进行扩展。 The intention behind the generic parameter <T extends Node> is to avoid casts.通用参数<T extends Node>背后的意图是避免强制转换。

When you execute this code, and click on the toggles, the output will be like:当您执行此代码并单击切换开关时,output 将如下所示:

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

I would propose one of the options that use the selectedProperty as the onActionProperty will change only if the button was pressed (by mouse, touch or key) or if you programatically call the fire() method.我建议使用selectedProperty的选项之一,因为onActionProperty只有在按下按钮(通过鼠标、触摸或键)或以编程方式调用fire()方法时才会更改。 The other two options will work always, even if you change the selected state programatically.其他两个选项将始终有效,即使您以编程方式更改所选的 state 也是如此。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM