2016-06-23 2 views
0

Я пересматриваю свой вопрос на основе комментариев. У меня есть JavaFX TableView, для которого количество столбцов флажка известно только во время выполнения. Итак, чтобы создать столбцы, я делаю:EDIT: Модель для 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? Если бы фиксированное число столбцов CheckBox, скажем, 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); 
} 
} 

Эта модель работает, если у меня есть один столбец строки и один столбец флажок. Но что мне делать, если у меня есть мультикарные столбцы флажка, для которых число известно только во время выполнения?

+4

Не могли бы вы объяснить, что вы пытаетесь достичь? Почему бы не изменить соответствующее свойство в модели, отображаемой таблицей? – Itai

+0

Поскольку у меня есть TableView с динамическим числом столбцов флажка, то есть количество столбцов может быть определено только во время выполнения. Поэтому я не могу использовать модель, потому что не знаю во время проектирования, сколько свойств мне действительно нужно. – user41854

+1

Как представляются данные? Даже если это в массивах или списках, которые все еще будут возможны. «TableView» использует виртуализацию ячеек, поэтому изменение элементов управления (UI) может ненадежно изменить все объекты данных. – Itai

ответ

1

Вы действительно не описал структуру данных, но это похоже, что есть какая-то коллекция String с (companyGroups) и каждая строка таблицы представлена ​​String (name) и один логический для каждый элемент companyGroups. Таким образом, один из способов сделать это было бы просто определить Map<String, BooleanProperty> в классе модели AttributeRow, где ключ на карте предназначено быть элементом 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); 
    } 
} 
+0

Ничего себе, спасибо James_D. Я впечатлен. Оно работает. Прошу извиниться перед моим бедным начальным вопросом. Спасибо, что помог мне в любом случае. :-) – user41854

Смежные вопросы