我正在根据评论来修改我的问题。我有一个Javafx TableView,仅在运行时知道复选框列的数量。因此,要创建列,我会做:
TableColumn attributeColumn = new TableColumn("Attribut");
attributeColumn.setCellValueFactory(new PropertyValueFactory<AttributeRow, String>("name"));
attributeTable.getColumns().add(attributeColumn);
for (String group : companyGroups)
{
TableColumn< AttributeRow, Boolean > groupColumn = new TableColumn<>( group );
groupColumn.setCellFactory(CheckBoxTableCell.forTableColumn(groupColumn));
groupColumn.setCellValueFactory( f -> f.getValue().activeProperty());
groupColumn.setEditable(true);
attributeTable.getColumns().add(groupColumn);
}
问题是,对于此tableView,表模型将如何?如果有固定数量的复选框列,例如2列,则我的型号如下:
public class AttributeRow {
private SimpleStringProperty name;
private SimpleBooleanProperty active = new SimpleBooleanProperty(false);
public AttributeRow(String name, Boolean active) {
this.name= new SimpleStringProperty(name);
}
public SimpleStringProperty nameProperty() {
if (name == null) {
name = new SimpleStringProperty(this, "name");
}
return name;
}
public String getAttributeName() {
return name.get();
}
public void setAttributeName(String fName) {
name.set(fName);
}
public final SimpleBooleanProperty activeProperty() {
return this.active;
}
public final boolean isActive() {
return this.activeProperty().get();
}
public final void setActive(final boolean active) {
this.activeProperty().set(active);
}
}
如果我有一个字符串列和一个复选框列,则此型号可以正常工作。但是我该怎么办,如果我有一个仅在运行时知道的数字的Muliple复选框列?
您尚未真正描述数据的结构,但是看起来有某种String
S(companyGroups
)的集合,并且每一行是表由String
表示(name
)和companyGroups
元素的一个布尔值。因此,这样做的一种方法就是在模型类AttributeRow
中定义Map<String, BooleanProperty>
,其中地图中的密钥旨在是companyGroups
的元素:
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
public class AttributeRow {
private final StringProperty name = new SimpleStringProperty();
private final Map<String, BooleanProperty> activeByGroup = new HashMap<>();
public AttributeRow(List<String> companyGroups) {
for (String group : companyGroups) {
activeByGroup.put(group, new SimpleBooleanProperty()) ;
}
}
public final BooleanProperty activeProperty(String group) {
// might need to deal with the case where
// there is no entry in the map for group
// (else calls to isActive(...) and setActive(...) with
// a non-existent group will give a null pointer exception):
return activeByGroup.get(group) ;
}
public final boolean isActive(String group) {
return activeProperty(group).get();
}
public final void setActive(String group, boolean active) {
activeProperty(group).set(active);
}
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);
}
}
列的单元格值工厂没有什么特别的 - 它仍然必须将每一行映射到列的适当可观察属性:
for (String group : groups) {
TableColumn<AttributeRow, Boolean> groupColumn = new TableColumn<>(group);
groupColumn.setCellFactory(CheckBoxTableCell.forTableColumn(groupColumn));
groupColumn.setCellValueFactory(cellData -> cellData.getValue().activeProperty(group));
attributeTable.getColumns().add(groupColumn);
}
,当然要更新值,您只需更新模型:
Button selectAll = new Button("Select all");
selectAll.setOnAction(e -> {
for (AttributeRow row : attributeTable.getItems()) {
for (String group : groups) {
row.setActive(group, true);
}
}
});
这是SSCCE:
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.CheckBoxTableCell;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;
public class TableWithMappedBooleans extends Application {
private static final List<String> groups = Arrays.asList("Group 1", "Group 2", "Group 3", "Group 4");
@Override
public void start(Stage primaryStage) {
TableView<AttributeRow> attributeTable = new TableView<>();
attributeTable.setEditable(true);
TableColumn<AttributeRow, String> attributeColumn = new TableColumn<>("Attribute");
attributeColumn.setCellValueFactory(cellData -> cellData.getValue().nameProperty());
attributeTable.getColumns().add(attributeColumn);
for (String group : groups) {
TableColumn<AttributeRow, Boolean> groupColumn = new TableColumn<>(group);
groupColumn.setCellFactory(CheckBoxTableCell.forTableColumn(groupColumn));
groupColumn.setCellValueFactory(cellData -> cellData.getValue().activeProperty(group));
attributeTable.getColumns().add(groupColumn);
}
// generate data:
for (int i = 1 ; i <= 10; i++) {
AttributeRow row = new AttributeRow(groups);
row.setName("Attribute "+i);
attributeTable.getItems().add(row);
}
// button to select everything:
Button selectAll = new Button("Select all");
selectAll.setOnAction(e -> {
for (AttributeRow row : attributeTable.getItems()) {
for (String group : groups) {
row.setActive(group, true);
}
}
});
// for debugging, to check data are updated from check boxes:
Button dumpDataButton = new Button("Dump data");
dumpDataButton.setOnAction(e -> {
for (AttributeRow row : attributeTable.getItems()) {
String groupList = groups.stream()
.filter(group -> row.isActive(group))
.collect(Collectors.joining(", "));
System.out.println(row.getName() + " : " + groupList);
}
System.out.println();
});
HBox buttons = new HBox(5, selectAll, dumpDataButton);
buttons.setAlignment(Pos.CENTER);
buttons.setPadding(new Insets(5));
BorderPane root = new BorderPane(attributeTable, null, null, buttons, null);
Scene scene = new Scene(root);
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}