So I have done some digging around on the JavaFx TableView and I have found some nice solutions to simple situations.
This article provides a nice explanation of how to
You don't have to use the default PropertyValueFactory, you can write your own callback.
import java.util.HashMap;
import java.util.LinkedHashMap;
import javafx.application.Application;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.Scene;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import javafx.util.Callback;
public class AssTable extends Application {
@Override
public void start(Stage primaryStage) {
ObservableList students = FXCollections.observableArrayList(
new Student("jack"),new Student("john"),new Student("jill"),new Student("jane"));
TableView studentTable = new TableView(students);
TableColumn firstNameColumn = new TableColumn("name");
firstNameColumn.setCellValueFactory(new PropertyValueFactory("firstName"));
studentTable.getColumns().add(firstNameColumn);
int maxAss = 0;
for (Student student : students)
maxAss = Math.max(maxAss, student.map.size());
Callback, ObservableValue> callBack =
new Callback, ObservableValue>() {
@Override
public ObservableValue call(TableColumn.CellDataFeatures param) {
return param.getValue().map.containsKey(
"ass"+Integer.toString((int)param.getTableColumn().getUserData()))
? new SimpleStringProperty(String.format("%.1f",100d*param.getValue().map.get(
"ass"+Integer.toString((int)param.getTableColumn().getUserData()))))
:new SimpleStringProperty("");
}
};
ObservableList> assCols = FXCollections.observableArrayList();
for (int i = 1; i<=maxAss; i++){
TableColumn tmpCol = new TableColumn("ass"+Integer.toString(i));
tmpCol.setUserData(i);
tmpCol.setCellValueFactory(callBack);
assCols.add(tmpCol);
}
studentTable.getColumns().addAll(assCols);
VBox root = new VBox(studentTable);
Scene scene = new Scene(root, 500, 250);
primaryStage.setTitle("Table with map");
primaryStage.setScene(scene);
primaryStage.show();
}
public class Student {
private final StringProperty firstName = new SimpleStringProperty();
public StringProperty firstNameProperty(){return firstName;}
public final HashMap map;
public Student(String fn) {
firstName.set(fn);
map = new LinkedHashMap<>();
for (int i = 1; i <= 10; i++) {
double grade = Math.random();
if (grade > .5) {
map.put("ass" + Integer.toString(i), grade);
}
}
}
}
}
You can see it adds columns depending on how many assignments there are. Also nobody has done ass4 in this random sample. With this code and example you can't add an assignment like #8 without also adding a new column, or it won't show up.