如何访问 ObservableList (JavaFX) 类型 class 中的方法

How to access a method in the type class of an ObservableList (JavaFX)

我有一个 ObservableList 类型的 Part,它包含多个 Part 对象。当向 ObservableList 添加一个新的 Part 时,我想检查一个变量 partID 的值是否等于其他 Parts 中相同变量 partID 的值。这是我现在设置代码的方式:

public class Inventory {
     public static ObservableList<Part> allParts = 
     FXCollections.observableArrayList();

     public static ObservableList<Part> getAllParts() {
          return allParts;
     }
}

public abstract class Part {
     public final IntegerProperty partID;

     public Part(int partID) {
          this.partID = new SimpleIntegerProperty(partID);
     }

     public void setPartID(int partID) {
          this.partID.set(partID);
     }
     public int getPartID() {
          return partID.get();
     }
}

现在,在我的 FXML 控制器中,我有以下代码,我尝试获取新 partID 的文本字段并检查是否有任何其他现有 partID 已经包含相同的值,以便我可以通知如果有,用户选择一个新的 partID,如果没有,则添加新的零件。

@FXML
void AddPartSaveButtonHandler(ActionEvent event) {
     if(partIDTextField.getText() != null) {
          String partIDString = partIDTextField.getText();
          int partID = Integer.parseInt(partIDString);

          if(partID != Inventory.getAllParts().getPartID() { 
               //getPartID() is redlined
               Inventory.getAllParts().add(newPart);
          }
     }
 }

当尝试从 getAllParts() 调用 getPartID() 时显然会出现编译错误,因为它不是它的一个实例。那么如何从 allParts 访问所有现有的 partID?

PS - partID 不是 ObservableList 中保存的唯一变量。我还有很多其他的(如 partName、partPrice 等),但我认为它们与问题的核心无关。

你唯一真正的选择是遍历列表并查看是否有任何现有的部分 ID 匹配(注意我已经更改了一些变量和方法的名称以符合正确的命名约定):

@FXML
void addPartSaveButtonHandler(ActionEvent event) {
     if(partIDTextField.getText() != null) {
          String partIDString = partIDTextField.getText();
          int partID = Integer.parseInt(partIDString);


          boolean hasMatch = false ;
          for (Part part : inventory.getAllParts()) {
              if (part.getPartID() == partID) {
                  hasMatch = true ;
                  break ;
              }
          }
          if (! hasMatch) { 
               //getPartID() is redlined
               Inventory.getAllParts().add(newPart);
          }
     }
 }

您可以使用流使这段代码更流畅(尽管它本质上做的是完全相同的事情):

@FXML
void addPartSaveButtonHandler(ActionEvent event) {
     if(partIDTextField.getText() != null) {
          String partIDString = partIDTextField.getText();
          int partID = Integer.parseInt(partIDString);


          boolean noneMatch = inventory.getAllParts().stream()
              .mapToInt(Part::getPartID)
              .noneMatch(id -> id == partID);

          if (noneMatch) { 
               //getPartID() is redlined
               Inventory.getAllParts().add(newPart);
          }
     }
 }

如果性能是个问题(每次添加新元素时都会遍历整个列表,如果添加很多元素可能会出现问题),那么您应该将 ID 保存在单独的数据结构中搜索速度更快。例如:

private Set<Integer> partIDs = new HashSet<>();

// ...

inventory.getAllParts().addListener((Change<? extends Part> c) -> {
    while (c.next()) {
        if (c.wasAdded()) {
            for (Part part : c.getAddedSubList()) {
                partIDs.add(part.getPartID());
            }
        }
        if (c.wasRemoved()) {
            for (Part part : c.getRemoved()) {
                partIDs.remove(part.getPartID());
            }
        }
    }
});

然后

@FXML
void addPartSaveButtonHandler(ActionEvent event) {
     if(partIDTextField.getText() != null) {
          String partIDString = partIDTextField.getText();
          int partID = Integer.parseInt(partIDString);

          if (! partIDs.contains(partID)) { 
               //getPartID() is redlined
               Inventory.getAllParts().add(newPart);
          }
     }
 }