带有 TableColumns 数组的 JavaFX TableView

JavaFX TableView with array of TableColumns

我有一个TableView<MonthRow>,我想在其中显示一年中的每个月及其相关日期。

我得到了那三个 类 用于演示目的:

public record DayCell(
        LocalDate date,
        DayType type
) {
    public String nameOfDay() {
        return DateTimeFormatter.ofPattern("EE", Locale.ENGLISH).format(date);
    }
}
public enum DayType {
    COMPASSIONATE_LEAVE("C"),
    EMPTY("E"),
    NOT_ON_PAYROLL("N"),
    QUARANTINE("Q"),
    REGULAR_LEAVE("R"),
    SICK_LEAVE("S"),
    TRAINING("TRG"),
    TRAVEL("T"),
    UNPAID_LEAVE("U");

    private final String shortName;

    DayType(String shortName) {
        this.shortName = shortName;
    }
}
public record MonthRow(
        String name,
        DayCell[] days // amount of days in that specific month
) {
}

然后我创建 table 内容:

public ObservableList<MonthRow> createMonth(int year) {
    MonthRow[] months = new MonthRow[12];
    for (int i = 0; i < months.length; i++) {
        LocalDate date = LocalDate.of(year, i + 1, 1);
        months[i] = new MonthRow(date.getMonth().getDisplayName(TextStyle.FULL, Locale.ENGLISH), createCells(date));
    }

    return FXCollections.observableArrayList(months);
}

public DayCell[] createCells(LocalDate date) {
    DayCell[] cells = new DayCell[date.lengthOfMonth()];

    for (int i = 0; i < cells.length; i++) {
        cells[i] = new DayCell(date.plusDays(i), DayType.EMPTY);
    }

    return cells;
}

现在有了用于 TableView 的 ObservableList,我有点卡住了。我想为月份设置一个 TableColumn,为 DayCell 设置 31 个 TableColumns。但是,因为它是一个数组,所以我不确定如何将每个 DayCell 的 cellData 反映到每个 TableCell 中。 另外,因为有些月份没有 31 天,因此, 单元格不应显示缺失日期的任何内容。

每个单元格应根据 DayType 显示 nameOfDay() 内容和颜色(将在某个时候在各自的 cellFactory 中完成)。

TableView Example

这可能是一个完全错误的方法,所以请不要犹豫,指导我寻找不同的解决方案。

你可以这样做:

TableView<MonthRow> table = new TableView<>();
TableColumn<MonthRow, String> monthColumn = new TableColumn<>("Month");
monthColumn.setCellValueFactory(cellData -> new SimpleStringProperty(cellData.getValue().getName()));
table.getColumns().add(monthColumn);

for (int i = 0; i < 31 ; i++) {
    TableColumn<MonthRow, DayCell> dayColumn = new TableColumn<>(Integer.toString(i+1));
    final int index = i ;
    dayColumn.setCellValueFactory(cellData -> {
        MonthRow month = cellData.getValue();
        if (index < month.getDays().size()) {
            return new SimpleObjectProperty<>(month.getDays()[index]);
        } else {
            return new SimpleObjectProperty<>(null);
        }
    });
    dayColumn.setCellFactory(new TableCell<>() {
        @Override
        protected void updateItem(DayCell day, boolean empty) {
            super.updateItem(day, empty);
            if (empty | day == null) {
                setText("");
            } else {
                setText(day.nameOfDay());
            }
        }
    });
    table.getColumns().add(dayColumn);
}

This might be a completely wrong approach

也许吧。您在这里需要 TableView 的功能吗?例如。选择一个月(行)等?也许 ScrollPane 中的简单 GridPane 会是一种更方便的方法;这实际上取决于您的项目要求。