我想问一下,有一种简单的方法可以向Observable列表添加约束,它只是属性的一个值。
例如:
我有一个可观察的人员名单。班级人员具有布尔属性" isKing"和字符串属性" guild"。每个公会只有一个国王。
当然,我可以(我知道如何)添加一个监听器来为其他人更改此属性的值,如果添加新的王。但还有其他方法吗?
(本地应用程序中没有用于管理数据集成的数据库......)
答案 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);
}
}