Как передать параметры в приложение JavaFX?

Я запускаю свое приложение JavaFX следующим образом:

public class MainEntry {
    public static void main(String[] args) {
        Controller controller = new Controller();
        Application.launch(MainStage.class);
    }
}

MainStage класс extends Appication. Application.launch запускает мое окно JavaFX в специальном потоке FX, но в моем основном методе у меня даже нет экземпляра моего класса MainStage.

Как передать параметр non-String (контроллер в моем случае) в экземпляр MainStage? Это ошибочный дизайн?

Ответ 1

Обычно нет необходимости передавать аргументы главному приложению, кроме аргументов программы, переданных в ваш основной. Единственная причина, по которой нужно сделать это, - создать многоразовый Application. Но Application не нужно повторно использовать, потому что это часть кода, которая собирает ваше приложение. Подумайте о том, что метод start будет новым main!

Поэтому вместо написания повторно используемого Application, который настроен в методе main, само приложение должно быть конфигуратором и использовать повторно используемые компоненты для создания приложения в методе start, например:

public class MyApplication extends Application {

    @Override
    public void start(Stage stage) throws Exception {
        // Just on example how it could be done...
        Controller controller = new Controller();
        MyMainComponent mainComponent = new MyMainComponent(controller);
        mainComponent.showIn(stage);
    }

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

Ответ 2

Вопрос - I

У меня даже нет экземпляра моего класса MainStage!

Решение

Ваш основной метод не нуждается в экземпляре MainStage, чтобы вызвать start() вашего MainStage. Это задание выполняется автоматически с помощью запуска JavaFX.

Из Документов

Точкой входа для приложений JavaFX является класс Application. Среда выполнения JavaFX делает следующее, в порядке, когда запускается приложение:

Создает экземпляр указанного класса Application

  • Вызывает метод init()
  • Вызывает метод start (javafx.stage.Stage)
  • Ожидает завершения работы приложения, которое происходит, когда происходит одно из следующих событий: приложение вызывает Platform.exit() последнее окно было закрыто, а атрибут implicitExit на платформе - true
  • Вызывает метод stop()

и

Java-пуск загружает и инициализирует указанное приложение класс в приложении JavaFX Application Thread. Если нет основного метода в класс Application, или если вызов основного метода Application.launch(), тогда экземпляр приложения затем построенный на JavaFX Application Thread.

Вопрос - II

Как передать параметр non-String (контроллер в моем случае) в экземпляр MainStage?

Решение

Зачем вам нужно передать параметр non-String в MainStage? Если вам нужен объект контроллера, просто выберите его из FXML

Пример

public class MainEntry extends Application {

    @Override
    public void start(Stage stage) throws Exception {
        FXMLLoader loader = new FXMLLoader();
        Pane pane = (Pane) loader.load(getClass().getResourceAsStream("sample.fxml"));
        //Get the controller
        Controller controller = (Controller)loader.getController();
        Scene scene = new Scene(pane, 200, 200);
        stage.setScene(scene);
        stage.show();
    }

    public static void main(String[] args) {
        launch(args);// or launch(MainEntry.class)
    }
}

Ответ 3

Начиная с JavaFX 9, вы можете запускать запуск платформы JavaFX "вручную" с использованием общедоступного API. Единственный недостаток заключается в том, что метод stop не вызывается так, как это было бы при запуске приложения через Application.launch:

public class MainEntry {
    public static void main(String[] args) {
        Controller controller = new Controller();

        final MainStage mainStage = new MainStage(controller);
        mainStage.init();

        Platform.startup(() -> {
            // create primary stage
            Stage stage = new Stage();

            mainStage.start(stage);
        });
    }
}

В потоке приложений JavaFX вызывается Runnable, переданный в Platform.startup.

Ответ 4

Массив String, переданный в метод main(), является параметрами приложения, а не специально для модуля JavaFX, если вы произвольно выбираете использование JavaFX.

Самым простым решением может быть хранение аргументов для последующего использования (например, статический атрибут рядом с методом main() и статический метод getter для доступа к нему).

Ответ 5

Вот хороший пример: в другом месте

@Override
public void init () throws Exception
{
  super.init ();

  Parameters parameters = getParameters ();

  Map<String, String> namedParameters = parameters.getNamed ();
  List<String> rawArguments = parameters.getRaw ();
  List<String> unnamedParameters = parameters.getUnnamed ();

  System.out.println ("\nnamedParameters -");
  for (Map.Entry<String, String> entry : namedParameters.entrySet ())
    System.out.println (entry.getKey () + " : " + entry.getValue ());

  System.out.println ("\nrawArguments -");
  for (String raw : rawArguments)
    System.out.println (raw);

  System.out.println ("\nunnamedParameters -");
  for (String unnamed : unnamedParameters)
    System.out.println (unnamed);
}

Ответ 6

Вы можете установить контроллер в классе MainStage. Но вам придется сделать это статическим, иначе оно будет равно null.

Посмотрите на код:

public class MainEntry {

  public static void main(String[] args) {
    Controller controller = new Controller();
    MainStage ms = new MainStage();
    ms.setController(controller);
    Application.launch(MainStage.class, (java.lang.String[]) null);
  }

}

public class MainStage extends Application {
  private static Controller controller;

  public void start(Stage primaryStage) throws Exception {
    System.out.println(controller);
    primaryStage.show();
  }

  public void setController(Controller controller){
    this.controller = controller;
  }

}

Ответ 7

Конечно, есть необходимость и возможность передавать параметры в приложение JavaFX.

Я сделал это для запуска моего клиента JavaFX из разных мест, где требуются разные сетевые конфигурации (прямой или через прокси). Чтобы не вносить мгновенные изменения в код, я реализовал несколько сетевых конфигураций, которые будут выбраны из команды запуска приложения с параметром, например - configurationIndex = 1. Значение по умолчанию - 0.

List<String> parameters;
int parameterIndex;
String parameter;

parameters =
  getParameters().getRaw();

for (parameterIndex = 0;
  parameterIndex < parameters.size();
  parameterIndex++) {

  parameter =
    parameters.get(
      parameterIndex);

  if (parameter.contains("configurationIndex")) {
    configurationIndex =
      Integer.valueOf(
        parameters.get(parameterIndex).
        split("=")[1]);
  }
}

В Netbeans вы можете установить этот параметр для отладки непосредственно в вашем проекте: Project - Properties - Run - Parameters - вставить - configurationIndex = 1 в поле.

Ответ 8

case 1 = стандартные типы java - передать их как строки java "--name = value", а затем преобразовать их в конечный пункт назначения, используя ответ dmolony

          for ( Map.Entry<String, String> entry : namedParameters.entrySet ()){
            System.out.println (entry.getKey() + " : " + entry.getValue ());              
            switch( entry.getKey()){
            case "media_url": media_url_received = entry.getValue(); break;
            }
      }

Параметр создается в Application.launch и декодируется в init

String args[] = {"--media_url=" + media_url, "--master_level=" + master_level};
Application.launch( args);

case 2 = Если вам нужно передать объекты Java, используйте этот обходной путь (это только для одного запуска приложения javafx, создайте карту обходных путей и отправьте индекс в виде строк, если у вас сложный случай)

    public static Transfer_param javafx_tp;

и в вашем классе init установите экземпляр объекта внутри статического класса

    Transfer_param.javafx_tp = tp1;

теперь вы можете статически найти свой последний объект для работы только с одним Приложением JavaFx (помните, что если у вас много активных приложений JavaFx, вы должны отправить String со статической идентификацией переменной внутри Map или массива, чтобы вы не брали поддельный объект адрес из ваших статических структур (используйте пример в случае 1 этого ответа для передачи --javafx_id = 3...))