2017-04-04 59 views
0

我想问你,有一个简单的方法可以将Observable列表添加到只有属性值为true的约束中。JavaFX Observable List只有一个属性值为true

例如:

我有一个可观察的人员名单。类人拥有布尔属性“isKing”和字符串属性“公会”。每个公会只能有一个国王。

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

(有当地aplication没有数据库来管理数据集成...)

+0

我会创造确定列表ha的方法是国王。那么你只需要使用if语句if(hasKing()){//什么也不做} else {add(Person)//谁是王者} – Sedrick

回答

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); 
    } 
} 

如果情况比较复杂(例如,单个人口和多个行业协会,每一个国王)相同的基本想法应该是可行的:定义一个模型类来封装你需要的任何数据结构,例如ObservableList<Person> populationObservableMap<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); 
    } 
}