Ошибка и бесконечный цикл при вызове метода в родительском контроллере FXML - PullRequest
0 голосов
/ 28 октября 2019

В настоящее время у меня есть приложение, которое использует несколько контроллеров FXML. В моем корневом контроллере (CustomController.java) я загрузил файл FXML, который вызывает MainMenuController. У меня есть другой контроллер / fxml-файл, который является еще одним «видом» приложения.

Мой вопрос таков: как лучше всего изменить текущее «представление»? Мой текущий метод вызывает CustomController.swapOut () при нажатии кнопки в mainmenu.fxml. Но это вызывает ошибку, так как он создает объект MainMenuController и застревает в бесконечном цикле, пока не заканчивается память.

Примечание. В настоящее время я пытаюсь сначала очистить панель viewableContent, прежде чем пытаться загрузить вновый "просмотр"

Application structure => tester.java -> CustomController.java
                                                  |
                                                  V
                                        customController.fxml -> MainMenuController.java
                                                                            |
                                                                            V
                                                                       mainmenu.fxml

tester.java

package task01;

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.stage.Stage;

public class tester extends Application
{
    @Override
    public void start(Stage stage) throws Exception
    {
        CustomController customController = new CustomController();

        customController.getStylesheets().add("/task01/stylize.css");

        stage.setScene(new Scene(customController,1920,1080));
        stage.setTitle("Seneca ATM Program");
        stage.setWidth(1920);
        stage.setHeight(1080);
        stage.show();
    }

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

CustomController.java

package task01;

import javafx.event.ActionEvent;
import javafx.scene.control.Button;
import javafx.scene.layout.GridPane;
import javafx.fxml.*;
import javafx.scene.layout.Pane;
import java.io.IOException;

public class CustomController extends GridPane
{

    @FXML
    private Pane viewableContent;

    public CustomController()
    {
        FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("customController.fxml"));

        fxmlLoader.setRoot(this);
        fxmlLoader.setController(this);

        try
        {
            fxmlLoader.load();
        } catch (IOException exception)
        {
            throw new RuntimeException(exception);
        }
    }

    public void swapOut()
    {
        viewableContent.getChildren().clear();
    }
}

customController.fxml

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.image.Image?>
<?import javafx.scene.image.ImageView?>
<?import javafx.scene.layout.GridPane?>
<?import javafx.scene.layout.Pane?>

<?import task01.MainMenuController?>
<fx:root type="javafx.scene.layout.GridPane" xmlns:fx="http://javafx.com/fxml" alignment="CENTER">
    <ImageView fitWidth="229.67" fitHeight="149.67" GridPane.columnIndex="0" GridPane.rowIndex="0" GridPane.halignment="CENTER">
        <Image url="/task01/logo.png"/>
    </ImageView>
    <Pane fx:id="viewableContent" GridPane.columnIndex="0" GridPane.rowIndex="1" GridPane.halignment="CENTER">
        <MainMenuController/>
    </Pane>
</fx:root>

MainMenuController.java

package task01;

import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.control.Button;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import java.io.IOException;

public class MainMenuController extends GridPane
{
    private CustomController customController = new CustomController();

    @FXML
    private VBox buttonSet;
    @FXML
    private HBox buttonSetOne;
    @FXML
    private HBox buttonSetTwo;
    @FXML
    private  Button changePinButton;
    @FXML
    private Button accountInquiryButton;
    @FXML
    private Button withdrawMoneyButton;
    @FXML
    private Button depositMoneyButton;
    @FXML
    private Button balanceInquiryButton;
    @FXML
    private Button createAccountButton;
    @FXML
    private GridPane gridpane;

    @FXML
    public void initialize()
    {
        createAccountButton.setOnAction(event ->
        {
            customController.swapOut();
        });
    }

    public MainMenuController()
    {
        FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("mainmenu.fxml"));
        fxmlLoader.setRoot(this);
        fxmlLoader.setController(this);

        try
        {
            fxmlLoader.load();
        } catch (IOException exception)
        {
            throw new RuntimeException(exception);
        }
    }
}

mainmenu.fxml

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.geometry.Insets?>

<fx:root type="javafx.scene.layout.GridPane" alignment="CENTER" vgap="50" hgap="50" xmlns:fx="http://javafx.com/fxml">
    <padding><Insets top="10" bottom="10" left="10" right="10"/></padding>
    <VBox fx:id="buttonSet" spacing="25" GridPane.columnIndex="0" GridPane.rowIndex="1">
        <HBox fx:id="buttonSetOne" spacing="25">
            <Button styleClass="menuButton" fx:id="createAccountButton">Create account</Button>
            <Button styleClass="menuButton" fx:id="changePinButton">Change PIN</Button>
            <Button styleClass="menuButton" fx:id="accountInquiryButton">Account Inquiry</Button>
        </HBox>
        <HBox fx:id="buttonSetTwo" spacing="25">
            <Button styleClass="menuButton" fx:id="withdrawMoneyButton">Withdraw Money</Button>
            <Button styleClass="menuButton" fx:id="depositMoneyButton">Deposit Money</Button>
            <Button styleClass="menuButton" fx:id="balanceInquiryButton">Balance Inquiry</Button>
        </HBox>
    </VBox>
</fx:root>

1 Ответ

0 голосов
/ 28 октября 2019

Обычно вам нужно передать «родительский» контроллер дочернему контроллеру вместо создания экземпляра в дочернем контроллере. (Экземпляр, с которым вы инициализируете свое поле, в любом случае будет отличаться от родительского экземпляра, что приведет к неработающему коду, даже если вы каким-то образом предотвратите переполнение стека.)

В этом случае вы можете использовать FXMLLoaderчтобы передать значение следующим образом:

<fx:root fx:id="rootController" type="javafx.scene.layout.GridPane" xmlns:fx="http://javafx.com/fxml" alignment="CENTER">
    <ImageView fitWidth="229.67" fitHeight="149.67" GridPane.columnIndex="0" GridPane.rowIndex="0" GridPane.halignment="CENTER">
        <Image url="/task01/logo.png"/>
    </ImageView>
    <Pane fx:id="viewableContent" GridPane.columnIndex="0" GridPane.rowIndex="1" GridPane.halignment="CENTER">
        <MainMenuController customController="$rootController"/> <!-- pass object to setter using fx:id -->
    </Pane>
</fx:root>

MainMenuController

private CustomController customController; //= new CustomController();

public void setCustomController(CustomController customController) {
    this.customController = customController;
}

// required for fxmlloader to identify the type
public CustomController getCustomController() {
    return customController;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...