簡體   English   中英

如何將FXML ComboBox實例從一個控制器傳遞到另一個?

[英]How to pass FXML ComboBox instance from one controller to another?

我有一個正在制作的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>

當您在generateScene()方法中創建newRoot時,傳遞給構造函數的組合框將被“覆蓋”。 創建newRoot ,然后將其用作要顯示的新場景的視圖,這就是組合框為空的原因。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM