Javafx pass parameter and values from one controller to another

后端 未结 1 921
花落未央
花落未央 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 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 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, 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)
提交回复
热议问题