registering changelistener to group of nodes in ja

2019-07-15 14:33发布

问题:

Is there any way to add a changelistener to group of nodes for following changes?

For example, we can add a changelistener to a tabpane for getting tabselectedproperty.

I want to add changelistener a to a group of buttons for getting buttonActionedProperty! I want to get old button and new button....

Is there any way to do this?

回答1:

When you compare the tabs in a tab pane to a collection of buttons, you're not really comparing like to like. A tab pane naturally has a sense of which tab is currently selected; buttons just generate events when they are pressed.

If you want your buttons to have a "selected" state, and want a collection of those grouped together so that only one is selected, then consider using ToggleButtons instead. You can put the toggle buttons into a ToggleGroup and register a listener with the toggle group's selectedToggle property:

import javafx.application.Application;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.ToggleButton;
import javafx.scene.control.ToggleGroup;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;

public class ToggleButtonDemo extends Application {

    @Override
    public void start(Stage primaryStage) {
        ToggleButton apples = new ToggleButton("Apples");
        ToggleButton oranges = new ToggleButton("Oranges");
        ToggleButton pears = new ToggleButton("Pears");

        ToggleGroup fruitToggleGroup = new ToggleGroup();
        fruitToggleGroup.getToggles().addAll(apples, oranges, pears);

        fruitToggleGroup.selectedToggleProperty().addListener((obs, oldToggle, newToggle) -> 
                System.out.println("Selected toggle changed from "+oldToggle+" to "+newToggle));

        HBox root = new HBox(5, apples, oranges, pears);
        root.setAlignment(Pos.CENTER);

        Scene scene = new Scene(root, 350, 75);
        primaryStage.setScene(scene);
        primaryStage.show();
    }

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

If you really just want buttons, and don't have the notion of one of them being selected (I find it hard to see a use case for this), you can just create an ObjectProperty<Button> to store the last button on which an action occurred. Register an event listener with each button to update the property:

import javafx.application.Application;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;

public class LastActionTrackingDemo extends Application {

    @Override
    public void start(Stage primaryStage) {
        Button apples = new Button("Apples");
        Button oranges = new Button("Oranges");
        Button pears = new Button("Pears");

        ObjectProperty<Button> lastActionedButton = new SimpleObjectProperty<>();

        EventHandler<ActionEvent> buttonActionHandler = event -> 
            lastActionedButton.set((Button) event.getSource());

        apples.addEventHandler(ActionEvent.ACTION, buttonActionHandler);
        oranges.addEventHandler(ActionEvent.ACTION, buttonActionHandler);
        pears.addEventHandler(ActionEvent.ACTION, buttonActionHandler);

        lastActionedButton.addListener((obs, oldButton, newButton) -> 
            System.out.println("Button changed from "+oldButton+" to "+newButton));

        HBox root = new HBox(5, apples, oranges, pears);
        root.setAlignment(Pos.CENTER);

        Scene scene = new Scene(root, 350, 75);
        primaryStage.setScene(scene);
        primaryStage.show();
    }

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

Note there is a subtle different between the appearance of the two demos. The first (with toggle buttons) has a visual representation of which button is selected. The second does not. In both cases you can still set action listeners on the buttons if you need that functionality. There is also a (less subtle) difference in behavior: the toggle buttons can be "unselected"; so if you press the same toggle button twice, the selection goes back to null. This doesn't happen with the buttons.