麻烦在场景之间传递参数

时间:2016-10-29 22:55:55

标签: java javafx

我正在写这个代码的问题。该项目是一个密码管理器应用程序,对于当前的sprint,我创建了一个Password模型和另一个类,用于保存名为ArrayList的{​​{1}}个Password。我在每个控制器类中创建了一个PasswordList对象作为PasswordList变量,并通过加载下一个场景的控制器并使用当前控制器设置private来传递它# 39; s PasswordList(以便在整个项目中传递相同的列表)。但是,在创建新的PasswordList对象时,将其添加到此Password,然后切换场景,PasswordListPasswordList

所以,我有一个null是观众,从那里用户可以点击"添加"按钮以查看PasswordUI。我已通过测试确保密码已创建并成功添加到CreatePasswordUI,方法是将其打印到控制台并使用调试器,所有内容都会检出。我甚至可以返回添加另一个密码,列表仍然包含所有以前创建的PasswordList个对象。然而,在Password中,即使我从前一个场景传递PasswordUIPasswordList仍然会以null出现。

我被困住了,不知道该怎么办。

PasswordList
public class PasswordUIController implements Initializable {

    private PasswordList passList;
    /**
     * Initializes the controller class.
     */
    @FXML
    TreeTableView passwordInfo;
    @FXML
    TreeTableColumn<String,String> acctColumn;
    @FXML
    Parent root;
    @FXML
    private void backButtonAction(ActionEvent event) throws Exception {
        Stage stage = (Stage) root.getScene().getWindow();
        FXMLLoader loader = new FXMLLoader(getClass().getResource("MainMenuUI.fxml"));     
        Pane mainMenuUI = (Pane)loader.load();          
        MainMenuController controller = loader.<MainMenuController>getController();
        controller.setPassList(passList);

        Scene scene = new Scene(mainMenuUI); 
        stage.setTitle("Main Menu");
        stage.setScene(scene);
        stage.show();
    }
    @FXML
    private void addButtonAction(ActionEvent event) throws Exception {
        Stage stage = (Stage) root.getScene().getWindow();
        FXMLLoader loader = new FXMLLoader(getClass().getResource("CreatePasswordUI.fxml"));     
        Pane createPassUI = (Pane)loader.load();          
        CreatePasswordUIController controller = loader.<CreatePasswordUIController>getController();
        controller.setPassList(passList);

        Scene scene = new Scene(createPassUI); 
        stage.setTitle("Create Password");
        stage.setScene(scene);
        stage.show();
    }
    @Override
    public void initialize(URL url, ResourceBundle rb) {
        PasswordList pList = passList;
        if (pList != null) {
            ArrayList<Password> thePasswords = pList.getPasswordList();           
            TreeItem<String> passwords = new TreeItem<>("Passwords");
            for (int i = 0; i < thePasswords.size(); i++) {
                Password thePass = thePasswords.get(i);
                //Creating tree items
                TreeItem<String> username = new TreeItem<>("Username: " + thePass.getUsername());
                TreeItem<String> password = new TreeItem<>("Password: " + thePass.getPassword());
                TreeItem<String> comment = new TreeItem<>("Comment: " + thePass.getComment());

                //Creating the root element
                TreeItem<String> account = new TreeItem<>(thePass.getAccount());
                account.setExpanded(true);

                //Adding tree items to the root
                account.getChildren().setAll(username, password, comment);   
                passwords.getChildren().add(account);
            }
            //Creating a column
            acctColumn = new TreeTableColumn<>("Account");

            //Defining cell content
            acctColumn.setCellValueFactory(new Callback<TreeTableColumn.CellDataFeatures<String, String>, ObservableValue<String>>() {
                @Override
                public ObservableValue<String> call(TreeTableColumn.CellDataFeatures<String, String> param){
                    return new SimpleStringProperty(param.getValue().getValue());
                }
            });

            //Creating a tree table view
            passwordInfo = new TreeTableView<>();
            passwordInfo.setRoot(passwords);
            passwordInfo.getColumns().add(acctColumn);
        } else {

        }
    }    

    /**
     * @return the passList
     */
    public PasswordList getPassList() {
        return passList;
    }

    /**
     * @param passList the passList to set
     */
    public void setPassList(PasswordList passList) {
        this.passList = passList;
    }

}

2 个答案:

答案 0 :(得分:0)

在每个控制器中都有一个新密码列表的问题是每次创建一个新实例时,你基本上都是在寻找单例方法。 您可以尝试使用单例,例如在整个应用程序中只创建一个对象,或者对于更简单的方法,您可以在主类中使用单个静态列表,然后在后续的控制器中重复使用它。

答案 1 :(得分:0)

如果使用fx:controller属性在fxml文件中指定控制器并且未指定控制器工厂,FXMLLoader将按以下步骤进行操作:

  1. load()方法已输入
  2. 读取fx:controller属性时,会创建属性值中指定的控制器类的新实例。
  3. 具有fx:id属性的任何元素都将注入控制器实例的适当字段。
  4. 如果有一个
  5. ,则调用控制器的initialize方法
  6. load()完成返回为fxml文件的根元素创建的元素
  7. 对于

    FXMLLoader loader = new FXMLLoader(getClass().getResource("CreatePasswordUI.fxml"));     
    Pane createPassUI = (Pane)loader.load();          
    CreatePasswordUIController controller = loader.<CreatePasswordUIController>getController();
    controller.setPassList(passList);
    

    但是你需要一个不同的操作顺序:

    1.
    2.
    3.
    5.
    controller.setPassList(passList);
    4.
    

    如果您想以这种方式创建控制器,请移动代码以将TreeTableView初始化为setPassList方法。

    BTW:我非常确定创建一个新的TreeTableView并不是你想要的。相反,您应该将数据设置为TreeTableView创建的现有FXMLLoader

    <强> PasswordUIController

    @Override
    public void initialize(URL url, ResourceBundle rb) {
        // displaying the item itself in the TreeTableColumn defys
        // the purpose of Tree**Table**View, but we'll ignore this here
        acctColumn.setCellValueFactory(new Callback<TreeTableColumn.CellDataFeatures<String, String>, ObservableValue<String>>() {
            @Override
            public ObservableValue<String> call(TreeTableColumn.CellDataFeatures<String, String> param){
                return new SimpleStringProperty(param.getValue().getValue());
            }
        });
    }
    
    public void setPassList(PasswordList passList) {
        if (passList == null) {
            throw new IllegalArgumentException();
        }
        this.passList = passList;
    
        ArrayList<Password> thePasswords = passList.getPasswordList();           
        TreeItem<String> passwords = new TreeItem<>("Passwords");
        for (int i = 0; i < thePasswords.size(); i++) {
            Password thePass = thePasswords.get(i);
            //Creating tree items
            TreeItem<String> username = new TreeItem<>("Username: " + thePass.getUsername());
            TreeItem<String> password = new TreeItem<>("Password: " + thePass.getPassword());
            TreeItem<String> comment = new TreeItem<>("Comment: " + thePass.getComment());
    
            //Creating the root element
            TreeItem<String> account = new TreeItem<>(thePass.getAccount());
            account.setExpanded(true);
    
            //Adding tree items to the root
            account.getChildren().setAll(username, password, comment);   
            passwords.getChildren().add(account);
        }
    
        // set content of the TreeTableView
        passwordInfo.setRoot(passwords);
    }
    

    还有其他方法可以将数据传递给fxml控制器。你可以在这里找到一些好的答案:Passing Parameters JavaFX FXML