JavaFX:设置满足条件的ObservableList的计数限制

时间:2017-04-03 07:38:08

标签: java 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个女性限制规则。
  3. 我该怎么做才能确保这一点?

1 个答案:

答案 0 :(得分: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);

这个解决方案唯一的问题是,它并没有真正&#34;还原&#34;更新更改,但将性别设置为新的未知值。

如果您想真正还原更改,解决方案可能类似于:

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