如何将FXML ComboBox实例从一个控制器传递到另一个?

时间:2019-01-04 17:40:49

标签: java oop user-interface javafx combobox

我有一个正在制作的JavaFX应用程序。我很难将组合框实例从一个屏幕传递到另一个屏幕。我的ComboBox变量称为reportBox。它在home.fxml中定义,并注入MyController.java中。当我尝试在MyController中切换屏幕时,我正在创建一个ReportScene对象(我制作的类),并将ComboBox传递给Report Scene的构造函数。报告场景也正在加载report.fxml。

在玩代码使之工作时,尝试设置reportScenebox的项目时我会得到一个错误,或者我不会收到任何错误,但Combobox将为空(因此似乎没有得到通过参考)。最终,如果我说reportSceneBox = MyController.SceneBox,则不必直接设置reportsene框的项目。我有时会根据代码的迭代而获得的错误是:ReportScene.reportBox = MyController.ReportBox,我得到“线程“ JavaFX Application Thread”中的异常“ java.lang.NullPointerException”。

我不明白为什么会发生此错误,或者为什么不能从Mycontroller.reportbox中正确填充/复制reportSceneBox。有人可以帮助您解释或帮助解决此问题吗?谢谢。

MyController.java

import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.scene.control.ComboBox;
import javafx.scene.control.MenuItem;
import javafx.scene.input.MouseEvent;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.collections.transformation.FilteredList;


public class MyController {

    private final static String[] REPORT_TYPES = {"Sales Report", "Inventory Report", "Guacamole Metrics"};


    @FXML
    private ComboBox<String> reportBox;

    private ObservableList<String> items = FXCollections.observableArrayList(REPORT_TYPES);


    public static final String[] getReportTypes()
    {
        return REPORT_TYPES;
    }

    /**
     * Initializes the controller class. This method is automatically called
     * after the fxml file has been loaded.
     */
    @FXML
    public void initialize()
    {
        //initialized drop down of report types
        reportBox.setItems(items);

        //Handles reportBox event
        reportBox.setOnAction((ActionEvent event) -> {
            String inputReport = reportBox.getValue();
            int reportIndex = indexOf(inputReport); //is do while loop here useful for input validation. it might not be, but something to consider. 
            if( reportIndex > -1)
            {
                System.out.println(reportIndex);
                ReportScene rs = new ReportScene(reportIndex, this.reportBox);
                //MATCH FOUND, create report scene;
            }
            else
            {
                // NO MATCH FOUND. NEED NEW INPUT.
            }
            // if input is valid, create new Report Scene of given REPORT_TYPE
            System.out.println(reportBox.getValue());
        });


    }

    private int indexOf(String reportType)
    {
        int index = -1;
        for(int i = 0; i < REPORT_TYPES.length; i++)
        {
            if(reportType.equalsIgnoreCase(REPORT_TYPES[i]))
            {
                index = i;
                i = REPORT_TYPES.length + 2;
            }
        }

        return index;
    }

Home.fxml

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

<?import javafx.scene.control.Button?>
<?import javafx.scene.control.DatePicker?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.Menu?>
<?import javafx.scene.control.MenuBar?>
<?import javafx.scene.control.MenuButton?>
<?import javafx.scene.control.MenuItem?>
<?import javafx.scene.control.SeparatorMenuItem?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.text.Font?>


<?import javafx.scene.control.ComboBox?>
<?import javafx.collections.FXCollections?>
<?import java.lang.String?>


<VBox prefHeight="600.0" prefWidth="1000.0" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="application.MyController">
  <children>
    <MenuBar VBox.vgrow="NEVER">
      <menus>
        <Menu mnemonicParsing="false" text="File">
          <items>
            <MenuItem mnemonicParsing="false" text="New" />
            <MenuItem mnemonicParsing="false" text="Open…" />
            <Menu mnemonicParsing="false" text="Open Recent" />
            <SeparatorMenuItem mnemonicParsing="false" />
            <MenuItem mnemonicParsing="false" text="Close" />
            <MenuItem mnemonicParsing="false" text="Save" />
            <MenuItem mnemonicParsing="false" text="Save As…" />
            <MenuItem mnemonicParsing="false" text="Revert" />
            <SeparatorMenuItem mnemonicParsing="false" />
            <MenuItem mnemonicParsing="false" text="Preferences…" />
            <SeparatorMenuItem mnemonicParsing="false" />
            <MenuItem mnemonicParsing="false" text="Quit" />
          </items>
        </Menu>
        <Menu mnemonicParsing="false" text="Edit">
          <items>
            <MenuItem mnemonicParsing="false" text="Undo" />
            <MenuItem mnemonicParsing="false" text="Redo" />
            <SeparatorMenuItem mnemonicParsing="false" />
            <MenuItem mnemonicParsing="false" text="Cut" />
            <MenuItem mnemonicParsing="false" text="Copy" />
            <MenuItem mnemonicParsing="false" text="Paste" />
            <MenuItem mnemonicParsing="false" text="Delete" />
            <SeparatorMenuItem mnemonicParsing="false" />
            <MenuItem mnemonicParsing="false" text="Select All" />
            <MenuItem mnemonicParsing="false" text="Unselect All" />
          </items>
        </Menu>
        <Menu mnemonicParsing="false" text="Help">
          <items>
            <MenuItem mnemonicParsing="false" text="About Report Generator" />
          </items>
        </Menu>
      </menus>
    </MenuBar>
    <AnchorPane maxHeight="-1.0" maxWidth="-1.0" prefHeight="-1.0" prefWidth="-1.0" VBox.vgrow="ALWAYS" id="pane">
      <children>
        <Label alignment="CENTER" layoutX="271.0" layoutY="26.0" style="&#10;" text="" textAlignment="CENTER" textFill="#9f9f9f" wrapText="false">
          <font>
            <Font size="18.0" />
          </font>
        </Label>
            <!-- <DatePicker layoutX="390.0" layoutY="44.0" />
            <DatePicker layoutX="189.0" layoutY="44.0" />
            <MenuButton layoutX="43.0" layoutY="44.0" mnemonicParsing="false" text="MenuButton">
              <items>
                <MenuItem mnemonicParsing="false" text="Sales Report 1" onAction="#processReport1" fx:id="menuItem1"/>
                <MenuItem mnemonicParsing="false" text="Inventory Report 1" />
                <MenuItem mnemonicParsing="false" text="InOut Report 1" />
              </items>
            </MenuButton> -->
            <Button layoutX="43.0" layoutY="317.0" mnemonicParsing="false" text="Run" />
            <ComboBox layoutX="43.0" layoutY="44.0" prefWidth="150.0" promptText="Select a Report" fx:id="reportBox" editable="True" >
              <items>
                <FXCollections fx:factory="observableArrayList">

                </FXCollections>
              </items>
            </ComboBox>
      </children>
    </AnchorPane>
  </children>
</VBox>

ReportScene.java

import java.util.Arrays;

import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ComboBox;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import javafx.scene.Parent;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;



public class ReportScene {

    private int reportIndex;
    private final String[] reportTypes = MyController.getReportTypes();
    private Scene reportScene;
    @FXML
    private ComboBox<String> reportSceneBox;
    private Button homeBtn;

    private final double[] reportWidths = new double[reportTypes.length];
    private final double[] reportHeights = new double[reportTypes.length];


    public ReportScene()
    {
        System.out.println("Default constructor for report scene");
    }

    public ReportScene(int reportIndex, ComboBox<String> reportBox)
    {
        //reportTypes = MyController.REPORT_TYPES;//getReportTypes();
        //destroy old scene and generate new one
        //destroy old scene here

        this.reportIndex = reportIndex;
        this.reportSceneBox = reportBox;
        //ObservableList<String> items = FXCollections.observableArrayList(MyController.getReportTypes());

        //this.reportSceneBox.setItems(items);
        //this.reportBox.setVisible(true);
        //this.homeBtn = new Button
        Arrays.fill(reportWidths, Main.getHomeWidth());
        Arrays.fill(reportHeights, Main.getHomeHeight());
        this.generateScene();
    }

    //@FXML
    public void generateScene()
    {
        try
        {
            Parent newRoot = FXMLLoader.load(getClass().getClassLoader().getResource("Reports/" + reportTypes[this.reportIndex] + ".fxml"));
            //newRoot.getChildrenUnmodifiable().add(this.reportBox);
            //newRoot.getParent().get

            Stage stageInstance = Main.getPrimaryStage();
//          @SuppressWarnings("unchecked")
//          ComboBox<String> ap = (ComboBox<String>) newRoot;
//          ap.getChildren().add(this.reportBox);
//          ap.setLayoutY(-580.0);
//          this.reportBox.setVisible(true);
            this.reportScene = new Scene(newRoot,reportWidths[this.reportIndex],reportHeights[this.reportIndex]);
            //this.reportScene.
            reportScene.getStylesheets().addAll(this.getClass().getResource("application.css").toExternalForm());
            stageInstance.setScene(this.reportScene);
            stageInstance.show();
        } 
        catch (Exception e) 
        {
            e.printStackTrace();
        }

report.fxml

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

<?import javafx.scene.control.Button?>
<?import javafx.scene.control.DatePicker?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.Menu?>
<?import javafx.scene.control.MenuBar?>
<?import javafx.scene.control.MenuItem?>
<?import javafx.scene.control.SeparatorMenuItem?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.text.Font?>

<?import javafx.scene.control.ComboBox?>
<?import javafx.collections.FXCollections?>
<?import java.lang.String?>

<VBox prefHeight="600.0" prefWidth="1000.0" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="application.ReportScene">
  <children>
    <MenuBar VBox.vgrow="NEVER">
      <menus>
        <Menu mnemonicParsing="false" text="File">
          <items>
            <MenuItem mnemonicParsing="false" text="New" />
            <MenuItem mnemonicParsing="false" text="Open…" />
            <Menu mnemonicParsing="false" text="Open Recent" />
            <SeparatorMenuItem mnemonicParsing="false" />
            <MenuItem mnemonicParsing="false" text="Close" />
            <MenuItem mnemonicParsing="false" text="Save" />
            <MenuItem mnemonicParsing="false" text="Save As…" />
            <MenuItem mnemonicParsing="false" text="Revert" />
            <SeparatorMenuItem mnemonicParsing="false" />
            <MenuItem mnemonicParsing="false" text="Preferences…" />
            <SeparatorMenuItem mnemonicParsing="false" />
            <MenuItem mnemonicParsing="false" text="Quit" />
          </items>
        </Menu>
        <Menu mnemonicParsing="false" text="Edit">
          <items>
            <MenuItem mnemonicParsing="false" text="Undo" />
            <MenuItem mnemonicParsing="false" text="Redo" />
            <SeparatorMenuItem mnemonicParsing="false" />
            <MenuItem mnemonicParsing="false" text="Cut" />
            <MenuItem mnemonicParsing="false" text="Copy" />
            <MenuItem mnemonicParsing="false" text="Paste" />
            <MenuItem mnemonicParsing="false" text="Delete" />
            <SeparatorMenuItem mnemonicParsing="false" />
            <MenuItem mnemonicParsing="false" text="Select All" />
            <MenuItem mnemonicParsing="false" text="Unselect All" />
          </items>
        </Menu>
        <Menu mnemonicParsing="false" text="Help">
          <items>
            <MenuItem mnemonicParsing="false" text="About MyHelloApp" />
          </items>
        </Menu>
      </menus>
    </MenuBar>
    <AnchorPane id="pane" maxHeight="-1.0" maxWidth="-1.0" prefHeight="-1.0" prefWidth="-1.0" VBox.vgrow="ALWAYS">
      <children>
        <Label alignment="CENTER" layoutX="384.0" layoutY="28.0" style="&#10;" text="Sales Report" textAlignment="CENTER" textFill="#9f9f9f" wrapText="false">
          <font>
            <Font size="18.0" />
          </font>
        </Label>
            <DatePicker layoutX="229.0" layoutY="91.0" />
            <DatePicker layoutX="464.0" layoutY="91.0" />
            <Label layoutX="229.0" layoutY="67.0" text="Start Date" />
            <Label layoutX="464.0" layoutY="67.0" text="End Date" />
            <Button fx:id="Run" layoutX="49.0" layoutY="496.0" mnemonicParsing="false" prefHeight="25.0" prefWidth="49.0" text="Run" />
            <ComboBox layoutX="43.0" layoutY="44.0" prefWidth="150.0" promptText="Select a Report" fx:id="reportSceneBox" editable="True" >
              <items>
                <FXCollections fx:factory="observableArrayList">
                </FXCollections>
              </items>
            </ComboBox>
            <!--  <Button fx:id="Home" layoutX="49.0" layoutY="41.0" mnemonicParsing="false" text="Home" /> -->
      </children>
    </AnchorPane>
  </children>
</VBox>

1 个答案:

答案 0 :(得分:0)

当您在newRoot方法中创建generateScene()时,传递给构造函数的组合框被“覆盖”。创建newRoot,然后将其用作要显示的新场景的视图,这就是组合框为空的原因。