Использование универсального типа для создания ObservableList - PullRequest
0 голосов
/ 02 сентября 2018

Я пытаюсь расширить класс JavaFX TableView, чтобы я мог буквально передать ему класс Entity, и он отобразит все сохраненные объекты для этого класса. Я могу заставить его работать так, но я хочу, чтобы мой пользовательский класс был достаточно универсальным, чтобы просто принимать переменную Class и заботиться об остальном:

private void showSuppliers()
{
    tabPane.getTabs().stream().filter((tab) -> (tab.getText().compareTo("Fournisseurs") == 0)).map((tab) -> (VBox)tab.getContent()).forEachOrdered((vBox) -> 
    {
        TableView<Supplier> table = new TableView<>();

        TableColumn nameColumn = new TableColumn("Nom");
        nameColumn.setCellValueFactory(new PropertyValueFactory<>("name"));

        TableColumn addressColumn = new TableColumn("Addresse");
        addressColumn.setCellValueFactory(new PropertyValueFactory<>("address"));

        TableColumn contactColumn = new TableColumn("Contact");
        contactColumn.setCellValueFactory(new PropertyValueFactory<>("contactPerson"));

        TableColumn phoneNumberColumn = new TableColumn("Téléphone");
        phoneNumberColumn.setCellValueFactory(new PropertyValueFactory<>("phoneNumber"));

        TableColumn emailColumn = new TableColumn("Courriel");
        emailColumn.setCellValueFactory(new PropertyValueFactory<>("emailAddress"));

        TableColumn creationDateColumn = new TableColumn("Date de création");
        creationDateColumn.setCellValueFactory(new PropertyValueFactory<>("enteredDate"));

        table.getColumns().addAll(nameColumn, addressColumn, contactColumn, phoneNumberColumn, emailColumn, creationDateColumn);

        ObservableList<Supplier> suppliers = FXCollections.observableArrayList(supplierService.findAll());
        table.setItems(suppliers);

        vBox.getChildren().add(table);
    });
}

Опять же, описанный выше метод работает отлично, но мне придется повторять его для каждой таблицы, в которой перечислены разные данные, которых я хочу избежать. Мой план состоит в том, чтобы расширить TableView универсальным типом, примерно так:

public class EntityTable<T> extends TableView<T>
{
    private final Class<T> entityClass;

    public EntityTable(Class<T> entityClass) 
    {
        this.entityClass = entityClass;

        init();
    }

    private void init()
    {
        for (Field field : entityClass.getDeclaredFields())
        {
            if ((field.getType() != Set.class) && (field.getName().compareTo("id") != 0))
            {
                TableColumn column = new TableColumn(field.getName());
                column.setCellValueFactory(new PropertyValueFactory<>(field.getName()));

                getColumns().add(column);
            }
        }
    }
}

Добавление столбцов не является проблемой, как вы можете видеть. Чего я не понимаю, так это как использовать мой T для создания чего-то вроде этого ObservableList:

ObservableList<Supplier> suppliers = FXCollections.observableArrayList(supplierService.findAll());

Я попытался просто заменить <Supplier> на <T> или <Class<T>>, и это, похоже, недопустимо. Я изучил Java еще тогда, когда этот материал почти не существовал, и информация, которую я нашел в Интернете о нем, немного смущает, если честно.

Как я могу построить свой список, используя переменную T в качестве типа?

Спасибо!

1 Ответ

0 голосов
/ 02 сентября 2018

Ну, это было просто, я просто удалил его! Вот конечный результат, просто передайте класс сущности и список, и таблица позаботится обо всем остальном!

public class EntityTable<T> extends TableView<T>
{
    private final Class<T> entityClass;

    private final List<T> entityList;

    public EntityTable(Class<T> entityClass, List<T> entityList) 
    {
        this.entityClass = entityClass;
        this.entityList = entityList;

        init();
    }

    private void init()
    {
        for (Field field : entityClass.getDeclaredFields())
        {
            if ((field.getType() != Set.class) && (field.getName().compareTo("id") != 0))
            {
                TableColumn column = new TableColumn(field.getName());
                column.setCellValueFactory(new PropertyValueFactory<>(field.getName()));

                getColumns().add(column);
            }
        }

        ObservableList list = FXCollections.observableArrayList(entityList);
        setItems(list);
    }
}

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

EDIT

Для имен столбцов я создал собственную аннотацию FriendlyName с параметром-значением. Теперь я заполняю заголовки столбцов так:

FriendlyName friendlyName = field.getAnnotation(FriendlyName.class);

TableColumn column = new TableColumn(friendlyName.value());
...