Как передать параметры в приложение 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...))