Инструкции по Javafx 2.0 Application.getParameters() в файле Controller.java

Учитывая следующий пример.

Как получить доступ к аргументам / параметрам приложения в контроллере?

Спасибо.


NB. Я пытался смешать App.java и MyController.java только в одном файле класса, но это не помогло.


App.java (упрощенно):

public class App extends Application {

    public static void main(String[] args) {
        Application.launch(App.class, args);
    }

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

        // output arguments in console
        System.out.println(getParameters().getNamed().toString());

        Parent root = FXMLLoader.load(getClass().getResource("MyView.fxml"));
        final Scene scene = new javafx.scene.Scene(root);
        primaryStage.setScene(scene);
        primaryStage.show();
    }

}

MyController.java (упрощенно):

public class MyController implements Initializable {

    @Override
    public void initialize(URL url, ResourceBundle rb) {
        // HOW TO getParameters() HERE ?
    }

    @FXML
    private Button myButton;

    @FXML
    private void my_Action(ActionEvent event) {
        // HOW TO getParameters() HERE ?
    }

}

MyView.fxml (упрощенно):

<AnchorPane fx:id="root" fx:controller="mainpackage.MyController">
    <children>
        <Button fx:id="myButton" onAction="#my_Action" text="Start" />
    </children>
</AnchorPane>

3 ответа

Решение

1. Самый простой способ - сохранить их в приложении:

public class App extends Application {

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

  public static String parameters;

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

    parameters = getParameters().getNamed().toString();

    Parent root = FXMLLoader.load(getClass().getResource("MyView.fxml"));
    final Scene scene = new javafx.scene.Scene(root);
    primaryStage.setScene(scene);
    primaryStage.show();
  }

}

и читать их в контроллере:

public class MyController implements Initializable {

  @Override
  public void initialize(URL url, ResourceBundle rb) {
     System.out.println(App.parameters);
  }

2. Более сложные (но лучше в целом) подходы описаны в следующих темах:

    public static <T extends Node, P> T load(String resource, final P parameter)
            throws MoisException {
        try {
            logger.debug("resource: {}; parameter: {}", resource, parameter);
            FXMLLoader loader = new FXMLLoader(getResource(resource));
            // pass parameter into Controller,before invoke the initialize()
            loader.setControllerFactory(new Callback<Class<?>, Object>() {
                @Override
                public Object call(Class<?> param) {
                    Object controller = null;
                    try {
                        controller = ReflectUtil.newInstance(param);
                    } catch (InstantiationException e) {
                        throw new MoisException("can't new instance for: " + param.getName(), e);
                    } catch (IllegalAccessException e) {
                        throw new MoisException("can't new instance for: " + param.getName(), e);
                    }
                    if (controller instanceof ParameterAware) {
                        ((ParameterAware<P>) controller).setParameter(parameter);
                    }
                    return controller;
                }
            });
            T node = (T) loader.load();
            // pass parameter to node
            node.setUserData(parameter);
            return node;
        } catch (IOException e) {
            throw new MoisException("can't load the file: " + resource, e);
        }
    }

и ParameterAware:

public interface ParameterAware<T> {
    void setParameter(T param);
}

каждый раз, когда вы загружаете файл fxml, он создает экземпляр контроллера, если вы можете получить этот экземпляр, вы можете передать много данных из класса, в котором вызывается fxml. это позволит избежать ненужных статических объектов.

      public class App extends Application {

    public static void main(String[] args) {
        Application.launch(App.class, args);
    }

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

        // output arguments in console
        System.out.println(getParameters().getNamed().toString());
        
        
        String parameters = getParameters().getNamed().toString();
        FXMLLoader fxmlLoader  = new FXMLLoader(this.getClass().getResource("MyView.fxml"));
                  
        Parent root = fxmlLoader.load();
        // cast MyController instance from fxmlLoader object
        MyController myController =(MyController)fxmlLoader.getController();
        // pass parameters string to myController via public method  setParameters()
        myController.setParameters(parameters);
        
        final Scene scene = new javafx.scene.Scene(root);
        primaryStage.setScene(scene);
        primaryStage.show();
    }

}

    

   

теперь вы получаете строку параметров из класса приложения в качестве частного поля в MyController

          public class MyController implements Initializable {

    private String parameters;

    // method called in App class
    public void setParameters(String parameters) {
        this.parameters = parameters;

    }

    @Override
    public void initialize(URL url, ResourceBundle rb) {
        // HOW TO getParameters() HERE ?
    }

    @FXML
    private Button myButton;
    @FXML
    private Label label;

    @FXML
    private void my_Action(ActionEvent event) {
        label.setText("parameters from App class in MyController :" + parameters);
    }

}

Я добавил метку в файл fxml, чтобы посмотреть, что произойдет.

       <AnchorPane id="AnchorPane" prefHeight="400.0" prefWidth="600.0" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/17" fx:controller="com.giovanni.mavenproject1.MyController">
    <children>
        <VBox alignment="CENTER" prefHeight="400.0" prefWidth="600.0" spacing="20.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
            <children>
                <Button fx:id="myButton" onAction="#my_Action" text="Start" />
                <Label fx:id="label" text="Label" />
            </children>
        </VBox>
    </children>  
</AnchorPane>

а это результат при нажатии кнопки

Другие вопросы по тегам