обратный вызов javafx checkBoxTableCell - PullRequest
0 голосов
/ 18 ноября 2018

Я хотел бы спросить, какой самый элегантный способ зафиксировать изменение значения CheckBoxTableCell в моем TableView.

Моя цель - сохранить новое значение в БД, которую показывает мой пример:

printedColumn.setCellValueFactory(f -> f.getValue().getPrintedProperty());
printedColumn.setCellFactory(CheckBoxTableCell.forTableColumn(new Callback<Integer, ObservableValue<Boolean>>() {
    @Override
    public ObservableValue<Boolean> call(Integer param) {
        ProductFx productFx = addProductModel.getProductFxObservableList().get(param);
        updateInDatabase(productFx);
        return productFx.getPrintedProperty();
    }
}));

Это прекрасно работает, но я не чувствую, что это лучший способ достичь этого.Для других столбцов я следую так:

@FXML
public void onEditPrice(TableColumn.CellEditEvent<ProductFx, Number> e) {
    ProductFx productFx = e.getRowValue();
    productFx.setPrice(e.getNewValue().doubleValue());
    updateInDatabase(productFx);
}

fxml:

<TableColumn fx:id="priceColumn" onEditCommit="#onEditPrice" prefWidth="75.0" text="%addProductTable.price" />

Возможно ли сделать это аналогичным образом с аннотированным методом @FXML и конфигурацией fxml?Может быть, другие идеи?

Ответы [ 2 ]

0 голосов
/ 11 августа 2019

Я не понимаю подробно, как у вас работает код.Я думаю, что это не работает, как задумано дизайном API.Я могу определенно ответить, если это возможно сделать с простым атрибутом FXML CheckBoxTableCell: Нет.

В случае CheckBoxTableCell

... это не обязательно, чтоячейка переходит в состояние редактирования (...).Побочным эффектом этого является то, что обычные редактирующие обратные вызовы (например, при редактировании) будут вызываться , а не .Если вы хотите получать уведомления об изменениях, рекомендуется непосредственно наблюдать логические свойства, которыми манипулирует CheckBox.

, как указано в javadoc .

Если класс printedProperty реализует ObservableValue<Boolean> (как указано в вашем коде), вы должны следовать цитируемому документу и добавить к нему ChangeListener, например

printedColumn.setCellValueFactory(f -> f.getValue().getPrintedProperty());
printedColumn.setCellFactory(CheckBoxTableCell.forTableColumn(new Callback<Integer, ObservableValue<Boolean>>() {
    @Override
    public ObservableValue<Boolean> call(Integer param) {
        ProductFx productFx = addProductModel.getProductFxObservableList().get(param);
        return productFx.getPrintedProperty();
    }
}));

ObservableList<ProductFx> obs = addProductModel.getProductFxObservableList();
obs.addListener(new ListChangeListener<ProductFx>(){
    @Override
    public void onChanged(Change<? extends ProductFx> c) {
        if(c.wasAdded()) {
            for (ProductFx s:c.getAddedSubList()) {
                s.getPrintedProperty().addListener(new ChangeListener<Boolean>() {
                    ProductFx localProductFx=s;                                 
                    @Override
                    public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) {
                        updateInDatabase(localProductFx);
                    }
                });
            }
        }   
    }
});

Но это не элегантно ввсе.

Ваш подход к решению проблемы:

Используемый вами Callback<Integer, ObservableValue<Boolean>>() вызывается каждый раз, когда отображаемая ячейка обновляется.Это особенно актуально, когда вы прокручиваете огромный список, потому что TableView сохраняет столько экземпляров Cell, сколько необходимо для заполнения его порта просмотра ( doc ).Они просто обновляются во время прокрутки, и ваш код обновляет базу данных каждый раз, когда это происходит, так что вы можете столкнуться с проблемами производительности для больших наборов данных или медленных баз данных.

PS: Насколько я понимаю, ваш код не выполняется обычные правила именования для свойств.Это может привести к проблемам при использовании отражающих классов, таких как PropertyValueFactory.

0 голосов
/ 19 ноября 2018

Мне действительно трудно понять идею вашего вопроса.Я публикую код, как я думаю, это должно быть сделано.Если это не соответствует вашим требованиям, уточните, чего именно вы пытаетесь достичь.

import javafx.application.Application;
import javafx.beans.property.LongProperty;
import javafx.beans.property.SimpleLongProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ListChangeListener;
import javafx.collections.ObservableList;
import javafx.scene.Scene;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.TextFieldTableCell;
import javafx.stage.Stage;

public class TableViewApp extends Application {

    public static void main(String[] args) {
        launch(args);
    }

    @Override
    public void start(Stage stage) throws Exception {

        ObservableList<Product> products = FXCollections.observableArrayList(product -> new ObservableValue[] {product.nameProperty()});
        products.add(new Product(1l, "Machine1"));
        products.add(new Product(2l, "Machine2"));
        products.addListener((ListChangeListener<Product>) change -> {
            while (change.next()) {
                if (change.wasUpdated()) {
                    for (int i = change.getFrom(); i < change.getTo(); i++) {
                        updateInDb(change.getList().get(i));
                    }
                }
            }
        });

        TableView<Product> tableView = new TableView<>(products);
        tableView.setEditable(true);

        TableColumn<Product, Long> idColumn = new TableColumn<>("Id");
        idColumn.setCellValueFactory(cellData -> cellData.getValue().idProperty().asObject());
        TableColumn<Product, String> nameColumn = new TableColumn<>("Name");
        nameColumn.setCellValueFactory(cellData -> cellData.getValue().nameProperty());
        nameColumn.setCellFactory(TextFieldTableCell.forTableColumn());
        nameColumn.setEditable(true);

        tableView.getColumns().add(idColumn);
        tableView.getColumns().add(nameColumn);

        stage.setScene(new Scene(tableView));
        stage.show();

    }

    private void updateInDb(Product product) {
        System.out.println("Update " + product + " in db");
    }
}

class Product {

    private LongProperty id = new SimpleLongProperty();
    private StringProperty name = new SimpleStringProperty();

    public Product(long id, String name) {
        this.id.set(id);
        this.name.set(name);
    }

    public LongProperty idProperty() {
        return id;
    }

    public long getId() {
        return id.get();
    }

    public StringProperty nameProperty() {
        return name;
    }

    public String getName() {
        return name.get();
    }

    @Override
    public String toString() {
        return "Product[id=" + getId() + ", name=" + getName() + "]";
    }
}
...