2017-04-03 66 views
1

我將用一個示例來解釋。JavaFX:滿足條件的ObservableList的設置計數限制

public class Person 
{ 
    private final ObjectProperty<Gender> gender; 
    public final ObjectProperty<Gender> genderProperty() 
    { 
     return this.gender; 
    } 
    public final void setGender(Gender value) 
    { 
     this.genderProperty().set(value); 
    } 
    public final Gender getGender() 
    { 
     return this.genderProperty().get(); 
    } 

    public static enum Gender { MALE, FEMALE } 

    /* Other properties */ 
} 

別的地方...

public class MyClass 
{ 
    private final ObservableList<Person> people; 
    public final ObservableList<Person> getPeople() 
    { 
     return this.people; 
    } 

    public MyClass() 
    { 
     // Create observable arraylist with extractor 
     this.people = FXCollections.observableArrayList(
      person -> new Observable[] 
       { 
        person.genderProperty() 
       } 
      ); 
    } 
} 

我需要people列表包含最多的10名男性和女性最大的5。一些Person對象不具有gender信息時,它被添加到people名單,但我的應用程序必須:

  1. 拿起這種變化,當這些Person對象的一個​​改變其gender和改變發生違反這個限制。
  2. 撤銷這樣的改變,以便我的規則總是適用於10個男性/ 5個女性的限制。

我該怎麼做才能確保這一點?

回答

1

首先你可以添加在Gender一個新的枚舉值表示未知性別:

public enum Gender { MALE, FEMALE, UNKNOWN }

然後你可以使用一個像ListChangeListener

this.people = FXCollections.observableArrayList(person -> new Observable[] {person.genderProperty()}); 

ListChangeListener<Person> listener = new ListChangeListener<Person>() { 

    private boolean checkCondition(ObservableList<Person> list, Person.Gender gender) { 
     int males = 0; 
     int females = 0; 

     for (Person person : list) { 
      switch (person.getGender()) { 
       case MALE: males++; break; 
       case FEMALE: females++; break; 
       default: break; 
      } 
     } 

     return ((males > 10 && gender == Person.Gender.MALE) || 
       (females > 5 && gender == Person.Gender.FEMALE)); 
    } 

    @Override 
    public void onChanged(Change<? extends Person> c) { 
     while (c.next()) { 
      if (c.wasAdded()) { 
       for (Person person : c.getAddedSubList()) { 
        if (checkCondition((ObservableList<Person>) c.getList(), person.getGender())) 
         c.getList().remove(person); 
       } 
      } 
      if (c.wasUpdated()) { 
       for (int update = c.getFrom(); update < c.getTo(); update++) { 
        Person person = c.getList().get(update); 
        if (checkCondition((ObservableList<Person>) c.getList(), person.getGender())) 
         person.setGender(Person.Gender.UNKNOWN); 
       } 

      } 
     } 
    } 
}; 

people.addListener(listener); 

唯一的問題與此解決方案,它並沒有真正「恢復」的更新變化,但設置性別爲新的未知值。


如果你想真正恢復更改,該解決方案可以是這樣的:

this.people = FXCollections.observableArrayList(); 

ListChangeListener<Person> listener = new ListChangeListener<Person>() { 

    private boolean checkCondition(ObservableList<Person> list, Person.Gender gender) { 
     int males = 0; 
     int females = 0; 

     for (Person person : list) { 
      switch (person.getGender()) { 
       case MALE: males++; break; 
       case FEMALE: females++; break; 
       default: break; 
      } 
     } 

     return ((males > 10 && gender == Person.Gender.MALE) || 
       (females > 5 && gender == Person.Gender.FEMALE)); 
    } 

    @Override 
    public void onChanged(Change<? extends Person> c) { 
     while (c.next()) { 
      if (c.wasAdded()) { 
       for (Person person : c.getAddedSubList()) { 

        if (checkCondition((ObservableList<Person>) c.getList(), person.getGender())) 
         c.getList().remove(person); 
        else 
         person.genderProperty().addListener((obs, oldval, newval) -> { 
          if (checkCondition((ObservableList<Person>) c.getList(), newval)) 
           person.setGender(oldval); 
         }); 
       } 
      } 
     } 
    } 
}; 

people.addListener(listener); 

差異:提取已被刪除,因爲ListChangeListener僅需添加元素的內部是覆蓋。當添加一個新元素時,其genderProperty上的偵聽器已添加哪一個偵聽性別更新,如果條件不滿足,則生成器將恢復爲原始狀態。


您也可以通過不暴露列表實現相同的功能,但操作列表方法:addPersonAtremovePersonAtupdateGenderAt

+0

我認爲第二個選項對我來說很好。謝謝! – Jai