调用父FXML控制器中的方法时出现错误和无限循环



我目前有一个使用多个FXML控制器的应用程序。在我的根控制器(CustomController.java(中,我加载了一个调用MainMenuController的FXML文件。我有另一个控制器/fxml文件,它是应用程序的另一个"视图"。

我的问题是:改变当前"观点"的最佳方法是什么?我目前的方法是在单击mainmenu.fxml中的按钮时调用CustomController.swapOut((。但这会导致错误,因为它正在创建MainMenuController对象,并陷入无限循环,直到内存耗尽。

注意:在尝试加载新的"视图"之前,我目前正在尝试先清除"可查看内容"窗格

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);
}
}
}

主菜单.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>

基本上,您需要将"父"控制器传递给子控制器,而不是在子控制器中创建实例。(初始化字段时使用的实例无论如何都会与父实例不同,这会导致代码无法工作,即使您以某种方式阻止堆栈溢出。(

在这种情况下,您可以使用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>

主菜单控制器

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;
}

最新更新