我正在写这个代码的问题。该项目是一个密码管理器应用程序,对于当前的sprint,我创建了一个Password
模型和另一个类,用于保存名为ArrayList
的{{1}}个Password
。我在每个控制器类中创建了一个PasswordList
对象作为PasswordList
变量,并通过加载下一个场景的控制器并使用当前控制器设置private
来传递它# 39; s PasswordList
(以便在整个项目中传递相同的列表)。但是,在创建新的PasswordList
对象时,将其添加到此Password
,然后切换场景,PasswordList
为PasswordList
。
所以,我有一个null
是观众,从那里用户可以点击"添加"按钮以查看PasswordUI
。我已通过测试确保密码已创建并成功添加到CreatePasswordUI
,方法是将其打印到控制台并使用调试器,所有内容都会检出。我甚至可以返回添加另一个密码,列表仍然包含所有以前创建的PasswordList
个对象。然而,在Password
中,即使我从前一个场景传递PasswordUI
,PasswordList
仍然会以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;
}
}
答案 0 :(得分:0)
在每个控制器中都有一个新密码列表的问题是每次创建一个新实例时,你基本上都是在寻找单例方法。 您可以尝试使用单例,例如在整个应用程序中只创建一个对象,或者对于更简单的方法,您可以在主类中使用单个静态列表,然后在后续的控制器中重复使用它。
答案 1 :(得分:0)
如果使用fx:controller
属性在fxml文件中指定控制器并且未指定控制器工厂,FXMLLoader
将按以下步骤进行操作:
load()
方法已输入fx:controller
属性时,会创建属性值中指定的控制器类的新实例。fx:id
属性的任何元素都将注入控制器实例的适当字段。initialize
方法
load()
完成返回为fxml文件的根元素创建的元素对于
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