Как создать несколько контроллеров javafx с разными файлами fxml?

Я просматривал некоторые блоги и другие вопросы, связанные с stackoverflow, и я не вижу прямого ответа на мой вопрос. Я создаю javafx gui client, и я хочу, чтобы моя строка была одним контроллером в одном fxml, а затем я хочу, чтобы область содержимого была дополнительным файлом fxml. Экран входа в систему будет одним fxml, после того, как экран входа в систему будет основным содержимым приложения и будет находиться в одном fxml. Как мне это сделать?

Я просто не хочу иметь весь свой код для моего входа, меню и основного содержимого в том же файле. Это образ того, над чем я работаю:

enter image description here

Ответы

Ответ 1

Используйте FXML в качестве компонентов, используя пользовательский класс java как fx: root и как fx: контроллер вашего файла FXML: http://docs.oracle.com/javafx/2/fxml_get_started/custom_control.htm

Для этого вам нужно вызвать конструктор вашего пользовательского класса java class FXMLLoader, который загрузит ваш FXML. Преимущество заключается в изменении способа загрузки компонентов FXML.

Классический способ создания компонентов с помощью FXMLLoader с вложенными контроллерами: сначала FXML, затем контроллер для каждой части.

С помощью этого метода это: сначала контроллер, затем FXML для каждого компонента. И вы не будете загружать FXML в FXML напрямую, вы импортируете свои пользовательские классы java в FXML.

Это лучшая абстракция (не нужно знать, как реализован компонент при импорте в FXML) и помогает повторно использовать код, поскольку он похож на реализацию пользовательского виджета с поддержкой FXML. Чтобы сделать ваш компонент многократным, убедитесь, что ваша реализация не имеет тесной связи с другими частями или использует IOC для этого (например, с Spring интеграцией с JavaFX). Таким образом, вы сможете самостоятельно импортировать свой компонент в любую часть вашего приложения (так же, как виджет DateInput), и вы не будете дублировать код.

В вашем случае у вас будет:

public class MenuBox extends VBox {

@FXML
private LoginBox loginBox;

@FXML
private ProfilesBox profilesBox;

public MenuBox() {
    FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("menu.fxml"));
    fxmlLoader.setRoot(this);
    fxmlLoader.setController(this);
    try {
        fxmlLoader.load();
    } catch (IOException exception) {
        throw new RuntimeException(exception);
    }
}

public class LoginBox extends VBox {
public LoginBox() {
    FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("login.fxml"));
    fxmlLoader.setRoot(this);
    fxmlLoader.setController(this);
    try {
        fxmlLoader.load();
    } catch (IOException exception) {
        throw new RuntimeException(exception);
    }
}

public class ProfilesBox extends VBox {
public ProfilesBox() {
    FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("profiles.fxml"));
    fxmlLoader.setRoot(this);
    fxmlLoader.setController(this);
    try {
        fxmlLoader.load();
    } catch (IOException exception) {
        throw new RuntimeException(exception);
    }
}

И вы импортируете LoginBox и ProfilesBox в menu.fxml, который управляет глобальным расположением вашей страницы:

<?import com.foo.bar.LoginBox ?>
<?import com.foo.bar.ProfilesBox ?>
<fx:root type="javafx.scene.layout.VBox"
    xmlns:fx="http://javafx.com/fxml">

<!-- Stuff here to declare the menu bar-->

    <HBox>
       <ProfilesBox fx:id="profilesBox"/>
       <LoginBox fx:id="loginBox"/>
    </HBox>

</fx:root>

login.fxml и profiles.fxml содержат только базовые компоненты.

Ответ 2

В документации вы можете настроить свой код таким образом, чтобы логику можно было отделить, а также вызвать из корневого контроллера (если необходимо).

Надеюсь, что это поможет.

Ответ 3

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

Проработав мои рекомендации, я нашел решение, которое может быть полезно.

Сначала я создал второй документ fxml и второй контроллер (в NetBeans, New → Empty FXML... → Использовать Java-контроллер → Создать новый...).

Немного сложно было выяснить, как построить сцену в главном контроллере и подключить ее к контроллеру всплывающих окон.

Ссылка Передача параметров JavaFX FXML дает некоторые реальные хорошие идеи и методы.

Последний код выглядит следующим образом (надеюсь, что это может помочь кому-то):

// Anchor Pane from the popup
@FXML
AnchorPane anchorPanePopup;

@FXML
private void soneButtonAction(ActionEvent event) throws IOException {     
    Stage newStage = new Stage();
    AnchorPane anchorPanePopup = (AnchorPane) FXMLLoader.load(getClass().getResource("Popup_FXML.fxml"));
    Scene scene = new Scene(anchorPanePopup);
    newStage.setScene(scene);
    newStage.initModality(Modality.APPLICATION_MODAL);
    newStage.setTitle("Dialog Window");
    newStage.showAndWait();        
}