防止 ObservableList 中的重复条目

Preventing duplicate entries in ObservableList

我好像不太对劲。我有一个包含类别项目的 listbox。我还有一个数据模型,它定义了 ID、姓名、姓氏、类别……和一个保存数据的 ObservableList。我正在尝试更新现有对象,以防用户单击 listbox 中的同一项目并更改姓名、姓氏。

这是我的代码:

public class FXMLDocController implements Initializable {

    ObservableList<String> listitems = FXCollections.observableArrayList(
                                        "Visual Basic", "ASP.net", "JavaFX");
    ObservableList<Persons> personData = FXCollections.observableArrayList();
    Persons pp = new Persons();

    private Label label;
    @FXML
    private TextField txtName;
    @FXML
    private TextField txtLastName;
    @FXML
    private Button btnSave;
    @FXML
    private TextArea txtArea;
    @FXML
    private ListView<String> listview = new ListView<String>();
    @FXML
    private Button btnTest;
    @FXML
    private Label lblCategory;
    @FXML
    private Label lblIndex;



    @Override
    public void initialize(URL url, ResourceBundle rb) {
        listview.setItems(listitems);

    }    

    @FXML
    private void handleSave(ActionEvent event) {

        String category = lblCategory.getText();
        boolean duplicate = false;
        //Add data. Check first if personData is empty

                if (personData.isEmpty()){
                    pp = new Persons(Integer.valueOf(lblIndex.getText()),category,txtName.getText(),txtLastName.getText());
                    personData.add(pp);
                }else{
                    for(int i = 0 ; i<personData.size() ; i ++){
                         if(Integer.toString(personData.get(i).getID()).equals(lblIndex.getText())){
                            duplicate = true;
                         }else{ 
                            duplicate = false;

                        }
                    }
                    System.out.println(duplicate);
                    if (duplicate == false){
                        pp = new Persons(Integer.valueOf(lblIndex.getText()),category,txtName.getText(),txtLastName.getText());
                        personData.add(pp);
                    }else{
                        System.out.println("Duplicate");
                    // Do Update later. 

                    }

                }

        //Show data to Test

            System.out.println("-- START OF LIST --");
        for (Persons person : personData){

            System.out.println(person.getID() + " " + person.getCategory()+ " " + person.getName() + " " + person.getLastname() + " " );
        }
        System.err.println(" ");
    }


    @FXML
    private void handleListClick(MouseEvent event) {
        lblCategory.setText(listview.getSelectionModel().getSelectedItem());
        lblIndex.setText(String.valueOf(listview.getSelectionModel().getSelectedIndex()));
    }
}

如果我在 listbox 上的一个项目上单击多次它工作正常..但是如果我单击 Visual Basic,然后 ASP.net 返回到 Visual Basic 它仍然接受它。 :( 需要建议和帮助。请

这是根据 Phil 的建议编写的代码

@FXML
private void handleSave(ActionEvent event) {

    String category = lblCategory.getText();
    boolean duplicate = false;
    int x = 0;
    //Add data

           Persons newPerson = new Persons(Integer.valueOf(lblIndex.getText()), category, txtName.getText(), txtLastName.getText());
             if (!personData.contains(newPerson)) {
                personData.add(newPerson);

             }else{
                 System.out.println("Duplicate!");
             }


    //Show data

        System.out.println("-- START OF LIST --");
    for (Persons person : personData){

        System.out.println(person.getID() + " " + person.getCategory()+ " " + person.getName() + " " + person.getLastname() + " " );
    }

}

这是我的人物 Class

public class Persons {
private SimpleIntegerProperty id;
private SimpleStringProperty name;
private SimpleStringProperty lastname;
private SimpleStringProperty category;



public Persons(){}
public Persons(int id, String category, String name, String lastname){
    this.id = new SimpleIntegerProperty(id);
    this.name = new SimpleStringProperty(name);
    this.lastname = new SimpleStringProperty(lastname);
    this.category = new SimpleStringProperty(category);


}
public Persons(String name, String lastname){
    this.name = new SimpleStringProperty(name);
    this.lastname = new SimpleStringProperty(lastname);
}

@Override
public boolean equals(Object o){
    if (o == this) return true;
    if (!(o instanceof Persons)){
        return false;
    }
    Persons persons = (Persons) o;

    return persons.id.equals(id) &&
            persons.name.equals(name) && 
            persons.lastname.equals(lastname) &&
            persons.category.equals(category);

}


//SETTERS
public void setID(int id) {
    this.id = new SimpleIntegerProperty(id);
}
public void setName(String name) {
    this.name = new SimpleStringProperty(name);
}
public void setLastname(String lastname) {
    this.lastname = new SimpleStringProperty(lastname);
}
public void setCategory(String category) {
    this.category = new SimpleStringProperty(category);
}

//GETTERS

public int getID() {
    return id.getValue();
}

public String getName() {
    return name.getValue();
}

public String getLastname() {
    return lastname.getValue();
}
public String getCategory(){
    return category.getValue();
}

// PROPERTIES

public SimpleIntegerProperty idProperty(){
    return this.id;
}
public SimpleStringProperty nameProperty(){
    return this.name;
}
public SimpleStringProperty lastnameProperty(){
    return this.lastname;
}
public SimpleStringProperty categoryProperty(){
    return this.category;
}

}

好的,这看起来不错。 equals 实现中的一件小事:

@Override
public boolean equals(Object o) {
    if (o == this) return true;
    if (!(o instanceof Persons)) {
        return false;
    }
    Persons persons = (Persons) o;

    // persons.id.equals() leads to the default implementation in Object 
    // --> instead use this one.
    // The Property classes have their own isEqualTo method
    // with get(), you will get your simple boolean from the returned BooleanBinding
    return persons.id.isEqualTo(id).get() &&
        persons.name.isEqualTo(name).get() &&
        persons.lastname.isEqualTo(lastname).get() &&
        persons.category.isEqualTo(category).get();

}

Object 的默认 equals 实现只是比较它是否是同一个实例。我们正在创建一个新实例并检查 contains(...) 列表是否包含 Persons.

这是我用来测试它的全部代码:

public class Main extends Application {

    private ObservableList<String> listitems = FXCollections.observableArrayList("Visual Basic", "ASP.net", "JavaFX");
    private ObservableList<Persons> personData = FXCollections.observableArrayList();

    private TextField txtName = new TextField();
    private TextField txtLastName = new TextField();
    private Button btnSave = new Button("save");
    private ListView<String> listview = new ListView<>();
    private Label lblCategory = new Label();
    private Label lblIndex = new Label();

    public static void main(String[] args) {
        launch(args);
    }

    @Override
    public void start(Stage stage) {
        listview.setItems(listitems);
        listview.setOnMouseClicked(this::handleListClick);
        btnSave.setOnAction(this::handleSave);

        VBox vb = new VBox(new HBox(5, new Label("Index:"), lblIndex),
            new HBox(5, new Label("Category:"), lblCategory),
            new HBox(5, new Label("Name:"), txtName),
            new HBox(5, new Label("Last name:"), txtLastName)
        );

        BorderPane bp = new BorderPane();
        bp.setLeft(listview);
        bp.setCenter(vb);
        bp.setRight(btnSave);

        Scene scene = new Scene(bp, 600, 400);
        stage.setScene(scene);
        stage.show();
    }


    private void handleSave(ActionEvent event) {
        Persons newPerson = new Persons(Integer.valueOf(lblIndex.getText()), lblCategory.getText(), txtName.getText(), txtLastName.getText());
        if (!personData.contains(newPerson)) {
            personData.add(newPerson);
        } else {
            System.out.println("Duplicate!");
        }

        System.out.println("-- START OF LIST --");
        for (Persons person : personData) {
            System.out.println(person);
        }

    }

    private void handleListClick(MouseEvent event) {
        System.out.println("click");
        lblCategory.setText(listview.getSelectionModel().getSelectedItem());
        lblIndex.setText(String.valueOf(listview.getSelectionModel().getSelectedIndex()));
    }


    public class Persons {
        SimpleIntegerProperty id;
        SimpleStringProperty name;
        SimpleStringProperty lastname;
        SimpleStringProperty category;

        Persons(int id, String category, String name, String lastname) {
            this.id = new SimpleIntegerProperty(id);
            this.name = new SimpleStringProperty(name);
            this.lastname = new SimpleStringProperty(lastname);
            this.category = new SimpleStringProperty(category);
        }

        @Override
        public boolean equals(Object o) {
            if (o == this) return true;
            if (!(o instanceof Persons)) {
                return false;
            }
            Persons persons = (Persons) o;

            // persons.id.equals() leads to the default implementation in Object
            // --> instead use this one.
            // The Property classes have their own isEqualTo method
            // with get(), you will get your simple boolean from the returned BooleanBinding
            return persons.id.isEqualTo(id).get() &&
                persons.name.isEqualTo(name).get() &&
                persons.lastname.isEqualTo(lastname).get() &&
                persons.category.isEqualTo(category).get();

        }

        @Override
        public String toString() {
            return "Persons{" +
                "id=" + id +
                ", name=" + name +
                ", lastname=" + lastname +
                ", category=" + category +
                '}';
        }
    }

}