Как установить массив вложенных объектов с переменным размером в качестве источника для javafx TableView TableColumns - PullRequest
0 голосов
/ 02 февраля 2019

У меня есть объект типа ClassTestEvaluation.Он содержит ArrayList типа Task.Этот массив может иметь любое количество задач и не является предсказуемым.Я хочу настроить табличное представление, которое будет отображать заданные задачи в столбцах, чтобы пользователь мог вводить точки.

Моя проблема в том, что я понятия не имею, как установить массив переменной длины, который является частью другого объекта, в качестве источника для моего табличного представления.Я не могу создать оболочку, такую ​​как ClassTestEvaluationItem, с простыми членами task1, task2 и т. Д., Поскольку число задач не фиксировано.Таким образом, мой вопрос заключается в том, что мне нужно сделать, чтобы правильно установить propertyValueFactories для столбцов задач?

Я следовал многим учебным пособиям, подобным приведенному здесь: https://docs.oracle.com/javafx/2/ui_controls/table-view.htm. Вообще говоря, проблем нети заставить их работать.Но они имеют дело только с простыми (плоскими) данными.

TableView<ClassTestEvaluation> table = new TableView<>();
TableColumn colFirstName = new TableColumn("Vorname");
colFirstName.setCellValueFactory(new PropertyValueFactory<ClassTestEvaluation, String>("firstName");
TableColumn colLastName = new TableColumn("Nachname");
colLastName.setCellValueFactory(new PropertyValueFactory<ClassTestEvaluation, String>("lastName");

table.getColumns().addAll(colFirstName, colLastName);

ArrayList<Task> tasks = classTestEvaluation.getTasks();
for(Task t : tasks) {
    TableColumn colTask = new TableColumn(t.getTitle());
    table.getColumns().add(colTask);
}

Как видите, несложно установить PropertyValueFactory для colFirstName и colLastName.Но как мне это сделать для задач, которые имеют переменную длину и хранятся в массиве, который сам является частью объекта ClassTestEvaluation?

В зависимости от количества задач, которые получил тест класса, я хочу, чтобы мое табличное представление выглядело так:

Имя |Фамилия |Задача 1 |Задача 2 |...

Я надеюсь, что кто-нибудь может помочь мне здесь, так как я не понимаю.Большое спасибо!

РЕДАКТИРОВАТЬ 1:

Чтобы сделать мой источник данных более понятным, вот соответствующая структура моих классов ClassTestEvaluation и Task:

public class ClassTestEvaluation{
    // ... more members ...
    ArrayList<Task> tasks = ArrayList<>();


    public ArrayList<Task> getTasks(){
        return this.tasks;
    }

    // ...more methods...

}



public class Task{
    private int id;
    private int idClassTestEvaluation;
    private Double points;
    private String title;

    public String getTitle(){
        return this.title;
    }

    public Double getPoints(){    // This methods needs to be connected as data source for tasks cells.
        return this.points;
    }

    // ...more methods...
}

Данные поступают из базы данных sqlite, где каждая задача связана через внешний ключ с определенной ClassTestEvaluation.При необходимости создается конкретная ClassTestEvaluation, которая заполняется соответствующими задачами.Таким образом, мне нужно найти способ сделать задачи (т.е. не только их заголовки в виде столбцов, но также их точки в виде ячеек) доступными и редактируемыми внутри табличного представления.

1 Ответ

0 голосов
/ 12 февраля 2019

Ну, я на самом деле нашел решение своего собственного вопроса и подумал, что это может быть интересно другим.Напомню: моя проблема заключалась в том, что я не знал, как построить столбцы из массива переменной длины, который является частью другого элемента (составлен).

Мне нужно было понять, как cellValueFactory, cellFactoryи onEditCommit может использоваться совместно с обратными вызовами или лямбдами соответственно для получения желаемого результата.Это заняло у меня довольно много времени.

Вот что я сделал, чтобы получить его:

    private void createTableColumnsForTasks(ClassTestEvaluation cte) {
    int resultCounter = 1;

    // For each given task in ClassTestEvaluation...
    for (Task t : cte.getTasks()) {

        // ...create a column for the corresponding points reached (0 in the beginning).
        TableColumn<ClassTestEvaluationRow, Double> colResult = new TableColumn<>("A" + resultCounter + " (" + t.getPoints() + ")");
        resultCounter++;

        // Make the column editable.
        colResult.setEditable(true);


        // Define how the values in the task columns will be set.
        colResult.setCellValueFactory((TableColumn.CellDataFeatures<ClassTestEvaluationRow, Double> row) -> {

            ClassTestEvaluationRow cter = row.getValue();

            for(Result r : cter.getResults()) {
                if(r.getIdTask() == t.getId()) {
                    ObservableValue<Double> obsResult = new SimpleObjectProperty<Double>(r.getPoints());
                    return obsResult;               
                }
            }

            return null;

        });



        // Create combo box to choose points from for each given task and result.
        createTableColumnComboBoxForResultEditing(colResult, t);


        // Create method to store edited data in selected ClassTestEvaluationRow.
        createOnEditCommitMethods(colResult, t);

        ((EvaluatorUI) this.getView()).getTableView().getColumns().add(colResult);

    }

}



private void createTableColumnComboBoxForResultEditing(TableColumn<ClassTestEvaluationRow, Double> colResult, Task t) {
    ArrayList<Double> cbPoints = new ArrayList<>();

    for(double i = 0.0; i <= t.getPoints(); i = i+0.5) {
        cbPoints.add(i);
    }

    ObservableList<Double> obsPoints = FXCollections.observableArrayList(cbPoints);

    colResult.setCellFactory(ComboBoxTableCell.<ClassTestEvaluationRow, Double>forTableColumn(obsPoints));      
}




private void createOnEditCommitMethods(TableColumn<ClassTestEvaluationRow, Double> colResult, Task t) {

    colResult.setOnEditCommit((CellEditEvent<ClassTestEvaluationRow, Double> event) -> {
        TablePosition<ClassTestEvaluationRow, Double> pos = event.getTablePosition();
        Double newValue = event.getNewValue();
        int row = pos.getRow();
        ClassTestEvaluationRow cter = (ClassTestEvaluationRow) event.getTableView().getItems().get(row);

        for(Result result : cter.getResults()) {
            if(result.getIdTask() == t.getId()){
                result.setPoints(newValue);
                classTestEvaluationsService.updateResult(cter.getClassTestEvaluation(), result);
            }
        }

    });

}

Я надеюсь, что это поможет некоторым из вас.Привет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...