Rene Ferguson
Rene Ferguson

Reputation: 39

How to concatenate event handler with another method call?

I have two buttons in two separate classes, and I want to change the onAction of the first button when the second button has been pressed to be the original action plus one additional method call. Once the first button has been pressed I want its onAction to revert to the original.

What I currently have working is essientially

  Button b1 = new Button("b1");
    b1.setOnAction((event)-> {
        oldActionMethod();
    });

   public void oldActionMethod(){
     //actual code
   }

b2.setOnAction((event)-> {
      //some stuff
      Button b1 = getB1(); 
      EventHandler<ActionEvent> temp = b1.getOnAction();
      b1.setOnAction((event) -> {
        b1class.oldActionMethod(); 
        additionalMethod();
        b1.setOnAction(temp);
      }); 
    });

In order to make this work I had to move the block of code that was originally in the setOnAction lambda expression to a helper function. Is there a cleaner way to do this? Something like this which would eliminate the need for the helper function?

b1.setOnAction((event)-> {
    //actual code
});

b2.setOnAction((event) -> {
        //stuff 
        Button b1 = getB1();
        EventHandler<ActionEvent> temp = b1.getOnAction();
        b1.setOnAction(b1.getOnAction() + methodCall());
        b1.setOnAction(temp);
        //stuff
});

The way I have it currently does work but it feels really hack-y so I am just interested to know if there is a better option where you could essentially concatenate an actionEvent with another method. Also if there is a way to not require storing the original event in a temp object and resetting it at the end. A possible solution would be if I could tell b2 to listen for the next time b1 is pressed, but I don't know if there is any way to do that when they are in two separate classes.

Upvotes: 0

Views: 926

Answers (1)

c0der
c0der

Reputation: 18792

One solution is to have a shared model class between the two classes containing the buttos.
See the following mcve. For conviniense the entire code can be copy-pasted into one file (FaMain.java) and run:

import javafx.application.Application;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.value.ObservableValue;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.ToggleButton;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

public class FxMain extends Application {

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

        Model model = new Model();
        AClass aClass = new AClass(model);
        BClass bClass = new BClass(model);
        Label show = new Label();
        show.textProperty().bind(model.getTextProperty());
        VBox root = new VBox(10);
        root.getChildren().addAll(aClass.getButton(),show, bClass.getButton());
        primaryStage.setScene(new Scene(root, 400,100));
        primaryStage.sizeToScene();
        primaryStage.show();
    }

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

class Model {

    private final BooleanProperty aButtonSelected;
    private final SimpleStringProperty textProperty;

    Model(){
        aButtonSelected = new SimpleBooleanProperty();
        textProperty= new SimpleStringProperty();
    }

    ObservableValue<? extends String> getTextProperty() {
        return textProperty;
    }

    BooleanProperty aButtonSelectedProperty(){
        return aButtonSelected;
    }

    void bButtonClicked() {
        textProperty.set(aButtonSelected.get() ? "Button clicked. Toggle IS selected" :
            "Button clicked. Toggle is NOT selected");
    }
}

class AClass{

    private final ToggleButton aButton;

    AClass(Model model) {
        aButton = new ToggleButton("Toogle");
        model.aButtonSelectedProperty().bind(aButton.selectedProperty());
    }

    ToggleButton getButton(){
        return aButton;
    }
}

class BClass{

    private final Button bButton;

    BClass(Model model) {
        bButton = new Button("Click");
        bButton.setOnAction(e->model.bButtonClicked());
    }

    Button getButton(){
        return bButton;
    }
}

enter image description here

Upvotes: 1

Related Questions