JavaFx 将场景 1 中的文本添加到第二个场景中的 ListView

JavaFx add text from scene 1 to ListView in second scene

我正在尝试制作一个 Javafx 程序,该程序将从场景一获取用户输入,并在按下按钮时将其显示在场景二的 ListView 中。此外,用户可以返回场景一并添加另一个输入,而在场景二中,用户可以删除列表视图中的一个输入。我有以下代码,但出于某种原因,它没有在前一个输入下面添加每个新输入,而是覆盖了第一个输入。你能帮我弄清楚吗?谢谢!

在场景一中我有以下代码

public class Controller {

    @FXML
    private TextField userEmail;

    @FXML
    public void handleRegisterButton(ActionEvent event) throws IOException{
        Data data = Data.getInstance();
        data.setEmailAddress(userEmail.getText());

        Parent viewEmailsParent = FXMLLoader.load(getClass().getResource("../view/viewUserEmails.fxml"));
        Scene viewEmailsScene = new Scene(viewEmailsParent);

        Stage window = (Stage) ((Node)event.getSource()).getScene().getWindow();

        window.setScene(viewEmailsScene);
        window.show();

    }

}

在第二个场景中,我试图处理其中的大部分内容,我有以下代码:

public class secondController implements Initializable {
    ObservableList<String> listOfEmails;

    @FXML
    ListView<String> emailList = new ListView<>();

    @FXML
    public void handleBackButton(ActionEvent event) throws IOException {
        Parent viewEmailsParent = FXMLLoader.load(getClass().getResource("../view/register.fxml"));
        Scene viewEmailsScene = new Scene(viewEmailsParent);

        Stage window = (Stage) ((Node)event.getSource()).getScene().getWindow();

        window.setScene(viewEmailsScene);
        window.show();
    }
    @FXML
    public void handleDeleteButton(ActionEvent event) throws IOException{
        String selected = emailList.getSelectionModel().getSelectedItem();
        listOfEmails.remove(selected);
    }

    @Override
    public void initialize(URL url, ResourceBundle resourceBundle) {
        listOfEmails = FXCollections.observableArrayList(Data.getInstance().getEmailAddress());
        emailList.setItems(listOfEmails);
    }
}

如果有帮助,这是数据class

public class Data {
    public static Data emailStorage;
    private String emailAddress;

    private Data(){
    }

    public static Data getInstance(){
        if(emailStorage == null){
            emailStorage = new Data();
        }
        return emailStorage;
    }

    public String getEmailAddress(){
        return emailAddress;
    }

    public void setEmailAddress(String emailAddress){
        this.emailAddress = emailAddress;
    }
}

因为您每次都重新加载 FXML 文件 viewUserEmails.fxml,所以每次都会创建一个新的 ListView 和可观察列表,只显示数据模型中的单个项目 class。

因此您的数据模型 class 应该包含完整列表,而不仅仅是最近添加的单个项目:

public class Data {
    public static Data emailStorage;
    private ObservableList<String> emailAddresses;

    private Data(){
    }

    public static Data getInstance(){
        if(emailStorage == null){
            emailStorage = new Data();
        }
        return emailStorage;
    }

    public ObservableList<String> getEmailAddresses(){
        return emailAddress;
    }

}

现在你可以做:

public class SecondController implements Initializable {

    // ...

    @FXML
    ListView<String> emailList ;

    // ...

    @Override
    public void initialize(URL url, ResourceBundle resourceBundle) {
        listOfEmails = FXCollections.observableArrayList(Data.getInstance().getEmailAddresses());
        emailList.setItems(listOfEmails);
    }

}

public class Controller {

    @FXML
    private TextField userEmail;

    @FXML
    public void handleRegisterButton(ActionEvent event) throws IOException{
        Data data = Data.getInstance();
        data.getEmailAddresses().add(userEmail.getText());

        // ...

    }

}

也可以考虑修改代码,让viewUserEmails.fxml只加载一次,重新显示。上面的代码仍然适用于该修改。

请注意,您的代码中还有大量与实际问题无关的其他错误:

  1. 您应该永远不要初始化带注释的字段@FXML。注意我替换了

     @FXML private ListView<String> emailList = new ListView<>();
    

     @FXML private ListView<String> emailList ;
    

    如果这给您带来空指针异常,则有其他问题

  2. 你的资源路径有误。如果将其捆绑为 jar 文件,它们将无法工作。参见

  3. 为您的数据模型使用单例不是一个好主意。 (通常使用单例反模式是个坏主意。)相反,最好创建数据模型的实例并将其传递给需要它的控制器。参见 Passing Parameters JavaFX FXML

  4. 坚持 Java 命名约定。它将使您的代码更容易被其他程序员阅读,并帮助语法高亮工具正确解释您的代码。