I agree with @Jai comment. If you are pretty much looking for a simple table view for one week data, then you can align your data to suite TableView requirements and then set the items. If you requirement is more like a calendar, then the below approach may not suite.
Below is the demo if you want to convert your Lesson objects to table view data models and display. I also included to add Lessons dynamically.
import javafx.application.Application;
import javafx.beans.property.SimpleObjectProperty;
import javafx.collections.FXCollections;
import javafx.collections.ListChangeListener;
import javafx.collections.ObservableList;
import javafx.geometry.Bounds;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.StackPane;
import javafx.stage.Popup;
import javafx.stage.Stage;
import javafx.util.Callback;
import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.List;
public class LessonPlanDemo extends Application {
SecureRandom rnd = new SecureRandom();
String[] rooms = {"Room1", "Room2", "Room3", "Room4", "Room5"};
String[] trooms = {"TR1", "TR2", "TR3", "TR4", "TR5"};
String[] subjects = {"Maths", "Science", "Physics", "Chemistry", "Drawing"};
ObservableList<Lesson> lessons;
@Override
public void start(Stage stage) throws Exception {
StackPane root = new StackPane();
Scene sc = new Scene(root, 640, 310);
stage.setScene(sc);
stage.setTitle("Lesson Plan");
stage.show();
lessons = FXCollections.observableArrayList(createData());
ObservableList<ClassHour> classHours = FXCollections.observableArrayList();
repopulate(lessons, classHours);
lessons.addListener((ListChangeListener) e -> repopulate(lessons, classHours));
TableView<ClassHour> tableView = new TableView<>();
for (int i = 0; i < 5; i++) {
int day = i;
TableColumn<ClassHour, Lesson> dayColumn = new TableColumn<>(WeekDay.values()[i].name());
dayColumn.setSortable(false);
dayColumn.setCellValueFactory(param -> new SimpleObjectProperty(param.getValue().dayLessons[day]));
dayColumn.setCellFactory(new Callback<TableColumn<ClassHour, Lesson>, TableCell<ClassHour, Lesson>>() {
@Override
public TableCell<ClassHour, Lesson> call(TableColumn<ClassHour, Lesson> param) {
return new TableCell<ClassHour, Lesson>() {
@Override
protected void updateItem(Lesson item, boolean empty) {
super.updateItem(item, empty);
setText(null);
setGraphic(null);
if (!empty) {
if (item != null) {
setText(item.toString());
} else {
Button btn = new Button("+ ADD");
btn.setOnAction(e -> {
tableView.getSelectionModel().select((ClassHour) getTableRow().getItem());
showAdd(day, ((ClassHour) getTableRow().getItem()).hour, btn);
});
setGraphic(new StackPane(btn));
}
}
}
};
}
});
tableView.getColumns().addAll(dayColumn);
}
tableView.setItems(classHours);
root.getChildren().add(tableView);
}
private void repopulate(List<Lesson> lessons, ObservableList<ClassHour> classHours) {
classHours.clear();
// Converting Lessons to ClassHour objects.
lessons.forEach(lesson -> {
ClassHour classHour = classHours.stream().filter(ch -> ch.hour == lesson.schoolHour).findFirst().orElse(null);
if (classHour == null) {
classHour = new ClassHour(lesson.schoolHour);
classHours.add(classHour);
}
classHour.dayLessons[lesson.weekDay.ordinal()] = lesson;
});
}
private void showAdd(int day, int hour, Button node) {
Popup popup = new Popup();
popup.setAutoHide(true);
GridPane pane = new GridPane();
pane.setPadding(new Insets(10));
pane.setVgap(10);
pane.setHgap(10);
pane.setStyle("-fx-background-color:black,yellow;-fx-background-insets:0,1;");
ChoiceBox<String> roomBox = new ChoiceBox<>();
roomBox.getItems().addAll(rooms);
pane.addRow(0, new Label("School room : "), roomBox);
ChoiceBox<String> trBox = new ChoiceBox<>();
trBox.getItems().addAll(trooms);
pane.addRow(1, new Label("Teaching room : "), trBox);
ChoiceBox<String> subjectBox = new ChoiceBox<>();
subjectBox.getItems().addAll(subjects);
pane.addRow(2, new Label("Subject : "), subjectBox);
Button add = new Button("Add");
add.setOnAction(e -> {
Lesson lesson = new Lesson(roomBox.getSelectionModel().getSelectedItem(), trBox.getSelectionModel().getSelectedItem(), subjectBox.getSelectionModel().getSelectedItem(), WeekDay.values()[day], hour);
lessons.add(lesson);
popup.hide();
});
Button cancel = new Button("Cancel");
cancel.setOnAction(e -> popup.hide());
HBox btns = new HBox(add, cancel);
btns.setAlignment(Pos.CENTER);
btns.setSpacing(10);
pane.add(btns, 0, 3, 2, 1);
popup.getContent().add(pane);
Bounds bnds = node.localToScreen(node.getLayoutBounds());
popup.show(node, bnds.getMinX(), bnds.getMinY() + node.getLayoutBounds().getHeight());
}
public static void main(String[] args) {
Application.launch(args);
}
private List<Lesson> createData() {
List<Lesson> lessons = new ArrayList<>();
for (int day = 0; day < 5; day++) {
for (int classHour = 1; classHour < 8; classHour++) {
if (rnd.nextInt(2) == 0) {
lessons.add(new Lesson(rooms[rnd.nextInt(5)], trooms[rnd.nextInt(5)], subjects[rnd.nextInt(5)], WeekDay.values()[day], classHour));
}
}
}
return lessons;
}
class ClassHour {
private Lesson[] dayLessons = new Lesson[7];
private int hour;
public ClassHour(int h) {
this.hour = h;
}
}
class Lesson {
private Room schoolRoom;
private Room teachingRoom;
private TeacherSpecialization teachingInfo;
private WeekDay weekDay;
private int schoolHour;
public Lesson(String sr, String tr, String subject, WeekDay wd, int hour) {
schoolRoom = new Room(sr);
teachingRoom = new Room(tr);
teachingInfo = new TeacherSpecialization(subject);
weekDay = wd;
schoolHour = hour;
}
@Override
public String toString() {
return "Room : " + schoolRoom.title + " - " + teachingRoom.title + "\nSubject : " + teachingInfo.subject;
}
}
class Room {
String title;
public Room(String t) {
this.title = t;
}
}
class TeacherSpecialization {
String subject;
public TeacherSpecialization(String s) {
this.subject = s;
}
}
enum WeekDay {
MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY;
}
}