JavaFx TableView (TV) с ObservableList (OL): как редактировать TV и автоматически обновлять OL

Я использую ObservableList, который прикреплен к TableView. Теперь, прежде всего, я хочу сделать TableView редактируемым, а затем, когда редактируются определенные поля, я хочу обновить соответствующий объект в ObservableList. Но почему-то я борюсь с получением обновленного значения из TableView. И если я использую

tv_column.setCellFactory(TextFieldTableCell.forTableColumn());

то я получаю сообщение об ошибке:

Exception in thread "JavaFX Application Thread" java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String

Моя фабрика ценности ячеек:

tv_column.setCellValueFactory(new PropertyValueFactory<SaleItem,Double>("quantity"));

Модели:

public interface SaleItem {
    void setProductName(String productName);
    void setPrice(double price);
    double getPrice();
    double getTotalPrice();
    void setTotalPrice();
    String getProductCode();
    String getProductCodeDescription();
    String getDescription();
    String getProductName();
}

public abstract class NonFuel implements SaleItem {
    public SimpleIntegerProperty quantity = new SimpleIntegerProperty();
    public SimpleDoubleProperty price = new SimpleDoubleProperty(0.0);
    public SimpleStringProperty productName = new SimpleStringProperty("");
    SimpleDoubleProperty totalPrice = new SimpleDoubleProperty(0.0);
    // getter and setter
}

public class Drinks extends NonFuel {
    public Drinks() {
        setProductName("Coffee");
        setPrice(2.20);
        setQuantity(1);
    }
    // getter and setter
}

Может ли кто-нибудь помочь получить новое значение с телевизора или обновить OL за ним?

Заранее спасибо.


person marshalluous    schedule 08.10.2017    source источник
comment
Опубликуйте свой класс модели и фабрику значений ячеек   -  person James_D    schedule 08.10.2017
comment
Спасибо @James_D. Ваш вклад действительно помог мне найти проблему   -  person marshalluous    schedule 13.10.2017


Ответы (1)


Я понял, что есть две проблемы:

  1. Двойное или целочисленное значение из моей модели необходимо преобразовать в строку и из нее. Я могу настроить это прямо в столбце:

    tv_column.setCellFactory(
        TextFieldTableCell.forTableColumn(
            new StringConverter<Double>() {
                @Override
                public String toString(Double object) {
                    return Double.toString(object);
                }
    
                @Override
                public Double fromString(String string) {
                    return Double.valueOf(string);
                }
            }
        )
    );
    
  2. С другой стороны, мне пришлось получить событие редактирования ячейки и присвоить новое значение элементу ObservableList. Затем мне пришлось обновить элемент и обновить TableView:

    tv_column.setOnEditCommit(
        new EventHandler<TableColumn.CellEditEvent<SaleItem, Double>>() {
            @Override
            public void handle(TableColumn.CellEditEvent<SaleItem, Double> event) {
                SaleItem saleItem =  event.getTableView().getItems().get(event.getTablePosition().getRow());
                saleItem.setQuantity(event.getNewValue());
                saleItem.updatePrice();
                tv.refresh();
            }
        }
    );
    
person marshalluous    schedule 13.10.2017
comment
не используйте table.refresh НИКОГДА - это аварийный API, если не может быть никакого механизма уведомления (что не так в вашем контексте). Вместо этого используйте observableList с экстрактором, чтобы список запускал событие обновления при изменении свойств в другие столбцы - person kleopatra; 13.10.2017