JavaFX Observable只列出一个值为true的属性

时间:2017-04-04 16:31:48

标签: javafx

我想问一下,有一种简单的方法可以向Observable列表添加约束,它只是属性的一个值。

例如:

我有一个可观察的人员名单。班级人员具有布尔属性" isKing"和字符串属性" guild"。每个公会只有一个国王。

当然,我可以(我知道如何)添加一个监听器来为其他人更改此属性的值,如果添加新的王。但还有其他方法吗?

(本地应用程序中没有用于管理数据集成的数据库......)

1 个答案:

答案 0 :(得分:1)

看起来这样的属性不应该是列表元素的一部分,而应该只是一个外部值。在你建议的例子中,你可以创建一个单独的类来封装你的列表和国王:

public class Guild {

    private final ReadOnlyObjectWrapper<Person> king = new ReadOnlyObjectWrapper<>();

    private final ObservableList<Person> members = FXCollections.observableArrayList();

    public ObservableList<Person> getMembers() {
        return members ;
    }

    public ReadOnlyObjectProperty<Person> kingProperty() {
        return king.getReadOnlyProperty();
    }

    public Person getKing() {
        return kingProperty().get();
    }

    public void setKing(Person king) {
        if (! population.contains(king)) {
            throw new IllegalArgumentException("king must be a member of the guild");
        }
        this.king.set(king);
    }
}

如果情况更复杂(例如,单个人口和多个公会,每个人都有一个国王),同样的基本思想应该是可行的:定义一个模型类,它封装了你需要的任何数据结构,例如{{1}和ObservableList<Person> population,后者为每个公会保留一个国王。

这是一个更复杂的例子:

Person.java:

ObservableMap<String, Person> kings

DataModel.java:

package model;

import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;

public class Person {

    private final StringProperty name = new SimpleStringProperty();
    private final StringProperty guild = new SimpleStringProperty();

    public Person(String name, String guild) {
        setName(name);
        setGuild(guild);
    }

    public final StringProperty nameProperty() {
        return this.name;
    }

    public final String getName() {
        return this.nameProperty().get();
    }

    public final void setName(final String name) {
        this.nameProperty().set(name);
    }

    public final StringProperty guildProperty() {
        return this.guild;
    }

    public final String getGuild() {
        return this.guildProperty().get();
    }

    public final void setGuild(final String guild) {
        this.guildProperty().set(guild);
    }

}

ConstrainedModelDemo.java:

package model;

import javafx.beans.value.ChangeListener;
import javafx.collections.FXCollections;
import javafx.collections.MapChangeListener.Change;
import javafx.collections.ObservableList;
import javafx.collections.ObservableMap;

public class DataModel {

    private final ObservableMap<String, Person> kings = FXCollections.observableHashMap() ;
    private final ObservableList<Person> population = FXCollections.observableArrayList() ;

    public DataModel() {

        // if a current king switches guild, remove them as king:
        ChangeListener<String> guildListener = (obs, oldGuild, newGuild) -> 
            kings.remove(oldGuild);
        kings.addListener((Change<? extends String, ? extends Person> c) -> {
            if (c.wasAdded()) {
                c.getValueAdded().guildProperty().addListener(guildListener);
            }
            if (c.wasRemoved()) {
                c.getValueRemoved().guildProperty().removeListener(guildListener);
            }
        });
    }

    public ObservableList<Person> getPopulation() {
        return population ;
    }

    public ObservableMap<String, Person> getKings() {
        return FXCollections.unmodifiableObservableMap(kings);
    }

    public void makeKing(Person person) {
        kings.put(person.getGuild(), person);
    }

}