2017-04-03 65 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