我想问你,有一个简单的方法可以将Observable列表添加到只有属性值为true的约束中。JavaFX Observable List只有一个属性值为true
例如:
我有一个可观察的人员名单。类人拥有布尔属性“isKing”和字符串属性“公会”。每个公会只能有一个国王。
当然,我可以(并且我知道如何)添加一个监听器来为其他人更改这个属性的值,如果新的国王将被添加。但是还有其他方法?
(有当地aplication没有数据库来管理数据集成...)
我想问你,有一个简单的方法可以将Observable列表添加到只有属性值为true的约束中。JavaFX Observable List只有一个属性值为true
例如:
我有一个可观察的人员名单。类人拥有布尔属性“isKing”和字符串属性“公会”。每个公会只能有一个国王。
当然,我可以(并且我知道如何)添加一个监听器来为其他人更改这个属性的值,如果新的国王将被添加。但是还有其他方法?
(有当地aplication没有数据库来管理数据集成...)
它似乎并不喜欢这样的属性应该是列表中的元素的一部分,而是应该只是一个外部值。在你建议的例子,你可以创建一个单独的类,封装你的清单,王:
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);
}
}
如果情况比较复杂(例如,单个人口和多个行业协会,每一个国王)相同的基本想法应该是可行的:定义一个模型类来封装你需要的任何数据结构,例如ObservableList<Person> population
和ObservableMap<String, Person> kings
,后者为每个公会保留一个王。
这里是一个更复杂的例子:
Person.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);
}
}
DataModel.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);
}
}
ConstrainedModelDemo.java:
package ui;
import java.util.List;
import java.util.Random;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import javafx.application.Application;
import javafx.beans.binding.Bindings;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.value.ObservableValue;
import javafx.scene.Scene;
import javafx.scene.control.CheckBox;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.ComboBoxTableCell;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
import model.DataModel;
import model.Person;
public class ConstrainedModelDemo extends Application {
@Override
public void start(Stage primaryStage) {
DataModel model = new DataModel();
List<String> guilds = IntStream.rangeClosed(1, 5).mapToObj(i -> "Guild "+i).collect(Collectors.toList());
Random rng = new Random();
List<Person> population = IntStream.rangeClosed(1, 100).mapToObj(i -> new Person("Person "+i, guilds.get(rng.nextInt(guilds.size())))).collect(Collectors.toList());
model.getPopulation().setAll(population);
TableView<Person> table = new TableView<>();
table.setEditable(true);
table.getItems().addAll(population);
table.getColumns().add(column("Name", Person::nameProperty));
TableColumn<Person, String> guildColumn = column("Guild", Person::guildProperty);
guildColumn.setCellFactory(ComboBoxTableCell.forTableColumn(guilds.toArray(new String[guilds.size()])));
table.getColumns().add(guildColumn);
TableColumn<Person, Boolean> kingCol = new TableColumn<>("King");
kingCol.setCellValueFactory(cellData -> {
Person p = cellData.getValue();
return Bindings.createBooleanBinding(() ->
p == model.getKings().get(p.getGuild()), p.guildProperty(), model.getKings());
});
kingCol.setCellFactory(tc -> new TableCell<Person, Boolean>() {
private final CheckBox checkBox = new CheckBox();
{
checkBox.setOnAction(e -> {
if (checkBox.isSelected()) {
model.makeKing(table.getItems().get(getIndex()));
} else {
model.getKings().remove(table.getItems().get(getIndex()).getGuild());
}
});
}
@Override
protected void updateItem(Boolean item, boolean empty) {
super.updateItem(item, empty);
if (empty) {
setGraphic(null);
} else {
checkBox.setSelected(item);
setGraphic(checkBox);
}
}
});
table.getColumns().add(kingCol);
TableView<String> kingTable = new TableView<>();
kingTable.getItems().addAll(guilds);
kingTable.getColumns().add(column("Guild", guild -> new SimpleStringProperty(guild)));
kingTable.getColumns().add(column("King", guild -> Bindings.createStringBinding(() -> {
if (guild == null) return null ;
Person king = model.getKings().get(guild);
if (king == null) return null ;
return king.getName() ;
}, model.getKings())));
BorderPane root = new BorderPane(table);
root.setRight(kingTable);
Scene scene = new Scene(root, 600, 600);
primaryStage.setScene(scene);
primaryStage.show();
}
private <S,T> TableColumn<S,T> column(String title, Function<S, ObservableValue<T>> prop) {
TableColumn<S,T> col = new TableColumn<>(title);
col.setCellValueFactory(cellData -> prop.apply(cellData.getValue()));
return col ;
}
public static void main(String[] args) {
launch(args);
}
}
我会创造确定列表ha的方法是国王。那么你只需要使用if语句if(hasKing()){//什么也不做} else {add(Person)//谁是王者} – Sedrick