【问题标题】:JavaFX: Setting count limit for an ObservableList fulfilling a conditionJavaFX:为满足条件的 ObservableList 设置计数限制
【发布时间】:2017-04-03 07:38:08
【问题描述】:

我会用一个例子来解释。

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 对象在添加到people 列表时没有gender 信息,但我的应用程序必须:

  1. 当这些Person 对象之一更改它的gender,并且该更改恰好违反了此限制时,就会执行此类更改。
  2. 撤消此类更改,以便我的 10 男/5 女限制规则将始终适用。

我能做些什么来确保这一点?

【问题讨论】:

    标签: java javafx observablelist


    【解决方案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

    【讨论】:

    • 我认为第二个选项对我很有用。谢谢!
    猜你喜欢
    • 2019-07-15
    • 1970-01-01
    • 2021-12-24
    • 2021-03-29
    • 1970-01-01
    • 2023-03-31
    • 2019-04-30
    • 2020-05-01
    • 1970-01-01
    相关资源
    最近更新 更多