Динамически добавлять строки в таблицу в JavaFX

Я пытаюсь прочитать из CSV-файла в одном классе, который перебирает содержимое CSV-файла, который принимает форму номера студента в столбце 1 и вопрос 1 для вопроса xAmount в столбцах и создает объект из строк в CSV-файл. В другом классе я создаю таблицу и пытаюсь динамически заполнить таблицу, используя содержимое файла CSV.

До сих пор я настраивал его так, чтобы столбцы динамически заполнялись на основе заголовков в файле CSV, однако всякий раз, когда дело доходит до строк, выдается ошибка: «ПРЕДУПРЕЖДЕНИЕ: не удается получить свойство« номер студента »в PropertyValueFactory: javafx. scene.control.cell.PropertyValueFactory@76afc271 с предоставленным типом класса: class java.lang.String" и делает это для каждого столбца в файле CSV. В любом случае я могу динамически заполнять строки?

Вот код для класса StudentCsv:

public class StudentCsv {
    private int[] marks;
    private String studentNumber;
    public StudentCsv(String studentNumber, int[] marks) {
        this.studentNumber=studentNumber;
        this.marks = marks;
    }
}

А вот код класса tableView:

public class tableViewTest implements Initializable {
    @FXML
    private TableView tableView;
    @Override
    public void initialize(URL url, ResourceBundle resourceBundle) {
        ArrayList<StudentCsv> testStudents = new ArrayList<>();

        StudentCsv studentCsv1 = new StudentCsv("40236387", new int[]{2, 3, 4, 5, 6});
        StudentCsv studentCsv2 = new StudentCsv("40236388", new int[]{7, 8, 9, 10, 11});
        StudentCsv studentCsv3 = new StudentCsv("40236388", new int[]{12, 13, 14, 15, 16});

        testStudents.add(studentCsv1);
        testStudents.add(studentCsv2);
        testStudents.add(studentCsv3);

        String[] columnNames = {"Student number", "q1", "q2", "q3", "q4", "q5"};

        ObservableList<StudentCsv> studentData = FXCollections.observableArrayList();
        for (int i = 0; i < testStudents.size(); i++) {
            studentData.add(testStudents.get(i));
        }
        tableView.setItems(studentData);
        for (int i = 0; i < columnNames.length; i++) {
            TableColumn<StudentCsv, String> column = new TableColumn<>(columnNames[i]);
            column.setCellValueFactory(param ->
                    new ReadOnlyObjectWrapper<>(param.getValue()).asString());
            column.setPrefWidth(75);
            tableView.getColumns().add(column);
        }
    }
}
public class Main extends Application {
    @Override
    public void start(Stage stage) throws IOException {
        try{
            Parent root = FXMLLoader.load(getClass().getResource("tableViewTest.fxml"));
            Scene scene = new Scene(root);
            stage.setScene(scene);
            stage.show();
        }catch (Exception e){
            e.printStackTrace();
        }

    }
    public static void main(String[] args) {
        launch();
    }
}
<?xml version = "1.0" encoding = "UTF-8"?>

<?import javafx.scene.control.TableView?>
<?import javafx.scene.layout.AnchorPane?>

<AnchorPane prefHeight = "400.0" prefWidth = "600.0" xmlns = "http://javafx.com/javafx/19" xmlns:fx = "http://javafx.com/fxml/1" fx:controller = "com.example.testfx.tableViewTest">
   <children>
      <TableView fx:id = "tableView" layoutX = "43.0" layoutY = "76.0" prefHeight = "286.0" prefWidth = "505.0" />
   </children>
</AnchorPane>

Когда таблица заполняется, она заполняется как

Посмотрите, может ли stackoverflow.com/questions/56462624/… помочь.

SedJ601 09.02.2023 16:37

Я думаю, что Джеймс заметил эту проблему в вашем коде и закрыл ее на основе этого. Ссылка, которой я поделился, должна дать вам некоторые идеи о том, как решить вашу проблему. Кроме того, похоже, что вы не используете библиотеку для анализа файла CSV. Я думаю тебе надо.

SedJ601 09.02.2023 17:31
минимальный воспроизводимый пример пожалуйста .. обязательно прочитайте и поймите эту справочную страницу, затем действуйте соответственно .. и помните М! :)
kleopatra 09.02.2023 17:59

В ответ на @ SedJ601 я перешел по этой ссылке, и теперь мои столбцы настроены по-другому. Однако есть новая проблема, когда мои строки заполняются правильным количеством строк, которые находятся в CSV-файле, но проблема заключается в том, что строки заполняются значениями имени столбца. то есть номер студента появляется в столбце, а затем 4 раза в строках ниже.

Cbrady 09.02.2023 18:22

Как это не исправление? Вам необходимо предоставить обратный вызов, который принимает каждый экземпляр модели строки (ваш StudentCsv объект) и возвращает ObservableValue обертку значения, которое будет отображаться в столбце. Очевидно, что у вас не может быть свойства под названием «номер студента», так как это даже недопустимое имя свойства.

James_D 09.02.2023 18:31

Вероятный дубликат заполнения TableView из студенческого CSV.

jewelsea 10.02.2023 00:06

Я предоставил минимальный воспроизводимый пример в соответствии с запросом, это было сделано в другом сообщении, но поскольку оно было удалено, могу ли я попросить повторно открыть вопрос?

Cbrady 10.02.2023 00:56

Продолжая мой предыдущий комментарий : кажется, что класс tableViewTest — это ваш класс контроллера FXML, но вы не опубликовали FXML.

Abra 10.02.2023 07:59

Ваша проблема в параметре, который вы передаете setCellValueFactory. Вы возвращаете объект StudentCsv, а не один из его атрибутов. И результат, который вы видите, вероятно, потому, что класс StudentCsv не переопределяет метод toString.

Abra 10.02.2023 08:03

файл fxml - это просто таблица с fxid tableView, я не думал, что это необходимо. Есть ли рекомендуемое решение этой проблемы?

Cbrady 10.02.2023 12:05

повторяя предыдущий комментарий @Abra. Вы возвращаете объект StudentCsv, а не один из его атрибутов - это ответ на строковое представление в ячейке. Пожалуйста, ознакомьтесь с руководством по использованию TableView. И в отношении: файл fxml - это просто таблица с fxid tableView. Я не думал, что это необходимо при условии, что это не минимально воспроизводимый пример, а просто фрагмент кода, бесполезный для воспроизведения проблемы без изменений (как это должно быть, и уже упоминалось в нескольких комментариях;)

kleopatra 10.02.2023 12:15

В предыдущем посте один из участников Stack Overflow сказал мне, что fxml не понадобится. Я сейчас отредактировал его, чтобы все было внутри.

Cbrady 10.02.2023 12:18

.. и начните исправлять эти нарушения именования - они режут глаз ;)

kleopatra 10.02.2023 12:18

хорошо, спасибо за редактирование :) но тогда @Abra был достаточно любезен, чтобы просмотреть ваш код и зорким взглядом заметил ошибку, исправил ее и был счастлив. Обязательно прочитайте и поймите javadoc CellDataFeatures (== тип параметра, переданный фабрике)

kleopatra 10.02.2023 12:20

Я рад, что @Abra заметил, где я ошибаюсь, но не уверен, почему вы должны постоянно комментировать снисходительные комментарии к моим сообщениям, лол. Я рад, если кто-то скажет мне, где я ошибаюсь или где моему посту не хватает глубины. Только не надо снисходительных замечаний. Спасибо.

Cbrady 10.02.2023 12:23
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
16
115
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Фабрика значений ячеек для столбца — это функция, которая берет объект, представляющий строку (это StudentCsv, что является ужасным названием для класса), и возвращает ObservableValue, содержащее значение, которое будет отображаться в этом столбце для этой строки (т. е. значение в каждой ячейке столбца). Функция применяется к каждой видимой строке таблицы, чтобы определить, что отображать в ячейках столбца.

Таким образом, ваша фабрика значений ячеек должна быть функцией, которая принимает Student и возвращает ObservableValue обертку значения для этого столбца. Фабрика значений ячеек первого столбца должна возвращать ObservableValue, содержащую studentNumber. Остальные фабрики значений ячеек столбцов должны возвращать ObservableNumber, содержащий соответствующий mark.

Итак, вам нужно начать с методов доступа для studentNumber и marks. Минимум:

public class Student {
    private int[] marks;
    private String studentNumber;
    public Student(String studentNumber, int[] marks) {
        this.studentNumber=studentNumber;
        this.marks = marks;
    }

    public String getStudentNumber() {
        return studentNumber;
    }

    public int[] getMarks() {
        return marks;
    }
}

Теперь ваши фабрики значений ячеек могут возвращать соответствующие значения для каждого столбца. Я исправил часть уродливого кода здесь. Я не уверен, почему у вас есть поле с именем studentNumber, которое является String (а не каким-то числовым типом), но я оставил его на случай, если для этого есть веская причина.

public class TableViewTest implements Initializable {
    @FXML
    private TableView<Student> tableView;
    @Override
    public void initialize(URL url, ResourceBundle resourceBundle) {
        ArrayList<Student> testStudents = new ArrayList<>();

        Student student1 = new Student("40236387", new int[]{2, 3, 4, 5, 6});
        Student student2 = new Student("40236388", new int[]{7, 8, 9, 10, 11});
        Student student3 = new Student("40236388", new int[]{12, 13, 14, 15, 16});

        testStudents.add(student1);
        testStudents.add(student2);
        testStudents.add(student3);

        String[] columnNames = {"Student number", "q1", "q2", "q3", "q4", "q5"};

        ObservableList<Student> studentData = FXCollections.observableArrayList();
        studentData.addAll(testStudents);
        tableView.setItems(studentData);

        TableColumn<Student, String> studentNumberColumn = new TableColumn<>("Student number");
        studentNumberColumn.setCellValueFactory(cellData -> new SimpleStringProperty(cellData.getValue().getStudentNumber()));
        tableView.getColumns().add(studentNumberColumn);

        for (int i = 1; i < columnNames.length; i++) {
            TableColumn<Student, Number> column = new TableColumn<>(columnNames[i]);
            final int marksIndex = i-1 ;
            column.setCellValueFactory(cellData ->
                    new SimpleIntegerProperty<>(cellData.getValue().getMarks()[marksIndex]));
            column.setPrefWidth(75);
            tableView.getColumns().add(column);
        }
    }
}

Это не проверено, поэтому могут быть опечатки.

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

Cbrady 10.02.2023 13:28

Другие вопросы по теме

Похожие вопросы

Java Spring загружает несколько баз данных, репозиторий использует неправильную базу данных
Java 17 «выражение 'switch' не охватывает все возможные входные значения» не отображается, если нет возврата
Как кодировать и отправлять сообщение ISO 8583 с помощью ASCII и Hexa?
Измените текстовое представление во фрагменте на основе положительных/отрицательных кнопок DialogAlert в Android Java
Лучший способ проверить, является ли новое значение логическим предшественником текущего значения
Не удается найти задачи, соответствующие «spring-boot: run», поскольку проект «spring-boot» не найден в корневом проекте «demo»
Плюсы и минусы определения графа как вложенных узловых объектов по сравнению со словарем?
Изменить список объекта одного из свойств, если найдено более 1 записи в группе в списке с использованием java 8
Потоки Java: рассчитать длину пути, используя список координат, используя функции потока
Не удается открыть swagger 2 в приложении Spring Boot 3