Javafx pass parameter and values from one controller to another

后端 未结 1 911
花落未央
花落未央 2020-12-03 00:20

I am new to JavaFx and hence I cannot find a solution to solve my problem

Suppose I have following application structure :

- views
      - first.fxml         


        
相关标签:
1条回答
  • 2020-12-03 00:47

    Use an observable StringProperty in the model:

    public class AppModel {
    
        private final StringProperty text = new SimpleStringProperty();
    
        public StringProperty textProperty() {
            return text ;
        }
    
        public final String getText() {
            return textProperty().get();
        }
    
        public final void setText(String text) {
            textProperty().set(text);
        }
    }
    

    Make your controllers have access to the model:

    public class FirstController {
    
        private final AppModel model ;
    
        @FXML
        private TextField textEnter ;
    
        public FirstController(AppModel model) {
            this.model = model ;
        }
    
        // action event handler for button:
        @FXML
        private void sendText() { 
            model.setText(textEnter.getText());
        }
    }
    

    and

    public class SecondController {
    
        private final AppModel model ;
    
        @FXML
        private TextArea txtView ;
    
        public SecondController(AppModel model) {
            this.model = model ;
        }
    
        public void initialize() {
            // update text area if text in model changes:
            model.textProperty().addListener((obs, oldText, newText) -> 
                txtView.setText(newText));
        }
    }
    

    The slightly tricky part now is that the controllers don't have a no-arg constructor, which means the default mechanism for the FXMLLoader to create them won't work. The easiest way is to set them manually. Remove both the <fx:controller> attributes from the FXML files, and then in your Main class do

    AppModel model = new AppModel();
    
    FXMLLoader firstLoader = new FXMLLoader(getClass().getResource("first.fxml"));
    firstLoader.setController(new FirstController(model));
    Parent firstUI = firstLoader.load();
    
    FXMLLoader secondLoader = new FXMLLoader(getClass().getResource("second.fxml"));
    secondLoader.setController(new SecondController(model));
    Parent secondUI = secondLoader.load();
    

    If you prefer to keep the <fx:controller> attributes in the FXML files, you can use a controllerFactory instead, which essentially instructs the FXMLLoader as to how to create a controller:

    AppModel model = new AppModel();
    
    Callback<Class<?>, Object> controllerFactory = type -> {
        if (type == FirstController.class) {
            return new FirstController(model);
        } else if (type == SecondController.class) {
            return new SecondController(model);
        } else {
            try {
                return type.newInstance() ; // default behavior - invoke no-arg construtor
            } catch (Exception exc) {
                System.err.println("Could not create controller for "+type.getName());
                throw new RuntimeException(exc);
            }
        }
    };
    
    FXMLLoader firstLoader = new FXMLLoader(getClass().getResource("first.fxml"));
    firstLoader.setControllerFactory(controllerFactory);
    Parent firstUI = firstLoader.load();
    
    FXMLLoader secondLoader = new FXMLLoader(getClass().getResource("second.fxml"));
    secondLoader.setControllerFactory(controllerFactory);
    Parent secondUI = secondLoader.load();
    

    You can make the controller factory even more flexible by using (more) reflection; basically you can implement the logic "if the controller type has a constructor taking an AppModel, call that constructor, otherwise call the no-arg constructor".

    If you are creating a large application which needs to do a lot of this, then you might consider using afterburner.fx, which is a framework that essentially allows you to inject the model into the controllers using annotations.

    0 讨论(0)
提交回复
热议问题