【问题标题】:Set cell value when editing another cell编辑另一个单元格时设置单元格值
【发布时间】:2018-02-15 05:03:29
【问题描述】:

我已阅读this,但我无法清楚地看到答案。

我要做的是从 TableColumn 中获取单元格内的值,当我将值插入另一个单元格时计算...

一小段代码。

colExistenciaF.setCellFactory(TextFieldTableCell.forTableColumn(new DoubleStringConverter()));
    colExistenciaF.setOnEditCommit(new EventHandler<TableColumn.CellEditEvent<Productos, Double>>() {
        @Override
        public void handle(CellEditEvent<Productos, Double> event) {
            event.getTableView().getItems().get(event.getTablePosition().getRow())
                    .setExistencia(event.getNewValue());

            // Code to place the calculated value in that other column
        }
    });

观察,我的“Existencia Actual”列是这样声明的:

@FXML
private TableColumn<Productos, Double> colExistenciaI;

还有“Existencia Actual”和“Diferencia”这一个列:

@FXML
private TableColumn<Productos, Double> colExistenciaF;
@FXML
private TableColumn<Movproductos, Double> colDiferencia;

这是因为我拥有存储初始库存 (Producto.class) 或产品存在的实体,但是当我需要进行交易或移动时,我使用另一个实体 (MovProducto.class)。我不知道这是否相关,但必须提及以防万一您需要更多上下文。

编辑


为了给你更多的背景信息,我正在使用 hibernate,所以我的 pojos 类不能使用(据我所知)StringProperty 或数据库中不存在的任何类型的数据类型。

这些是我在这个问题中使用的pojo:

这些是我的控制器(不考虑 DAO 类的坏名声)

最后是databaseFXML file


提前感谢 James_D 博士。 :)

【问题讨论】:

  • “我正在使用休眠,所以我的 pojos 类不能使用(据我所知)StringProperty”不是真的。见,例如svanimpe.be/blog/properties-jpa
  • @James_D 抱歉,我不想发表这样的声明,据我所知,我正在努力表达这一点。再次感谢。
  • @James_D 照你说的做,并按照你的例子here,我遇到了另一个问题,我认为是关于休眠映射注释,Error when trying to map a Set type object 我已经为此创建了another 问题问题,但仍然找不到解决方案。你能帮我解决这个问题吗?
  • 是的。我看到了。我没有同时使用休眠和具有 JavaFX 属性的集合。如果我以后有时间,我会看看我是否能找到解决方案......
  • @James_D 谢谢!我把练习项目上传到了github,有兴趣的可以看看here is it

标签: java javafx javafx-8


【解决方案1】:

我创建了一个您可以查看的简单示例。

public class Controller implements Initializable {

    @FXML
    private TableView<Model> table;

    @FXML
    private TableColumn<Model, Double> initial;
    @FXML
    private TableColumn<Model, Double> actual;
    @FXML
    private TableColumn<Model, Double> diff;

    @Override
    public void initialize(URL location, ResourceBundle resources) {
        initial.setCellValueFactory(data -> data.getValue().initialProperty().asObject());
        actual.setCellValueFactory(data -> data.getValue().actualProperty().asObject());
        diff.setCellValueFactory(data -> data.getValue().differenceProperty().asObject());

        initial.setCellFactory(factory -> new TextFieldTableCell<>(new DoubleConverter()));
        actual.setCellFactory(factory -> new TextFieldTableCell<>(new DoubleConverter()));

        table.setEditable(true);
        diff.setEditable(false); // I think it makes sense to set non-editable

        ObservableList<Model> data = FXCollections.observableArrayList();

        data.add(new Model(10D, 9D));
        data.add(new Model(98D, 45D));

        table.setItems(data);
    }

    class Model {

        private DoubleProperty initial;
        private DoubleProperty actual;
        private DoubleProperty difference;

        public Model(Double initial, Double actual) {
            this.initial = new SimpleDoubleProperty(initial);
            this.actual = new SimpleDoubleProperty(actual);
            this.difference = new SimpleDoubleProperty(initial - actual);
            // Here is where the "magic" happens :)
            this.difference.bind(this.initial.subtract(this.actual));
        }

        public double getInitial() {
            return initial.get();
        }

        public DoubleProperty initialProperty() {
            return initial;
        }

        public double getActual() {
            return actual.get();
        }

        public DoubleProperty actualProperty() {
            return actual;
        }

        public double getDifference() {
            return difference.get();
        }

        public DoubleProperty differenceProperty() {
            return difference;
        }
    }

    class DoubleConverter extends StringConverter<Double> {

        @Override
        public String toString(Double object) {
            return object.toString();
        }

        @Override
        public Double fromString(String string) {
            return Double.valueOf(string);
        }
    }

}

当然你可以在那里处理一些事情,比如NumberformatException。但是你想解决我认为它有效。

【讨论】:

  • 我应该放置更多代码以提供更多上下文,因为我正在尝试(非常努力)以获得您的解决方案,我认为这不是我需要的方法并且这就是为什么:我的模型或实体由 String 和 double 字段组成,因为我使用的是 hibernate,并且正如我目前所见,实体 pojos 应该具有这些类型的字段(String、double、int)。所以我要为这个问题添加更多代码。非常感谢你,希望你能帮助我。
  • 我认为将 pojos 用作 UI 中的模型是一种非常糟糕的做法。你可以简单地为你的TableView 创建一个模型,然后将你的 pjos 的字段传递给它的构造函数,然后你很容易分离 pojos 和 UI 模型,它也解决了这个问题。
  • 没有理由不在 JPA 实体中使用 JavaFX 属性;只需确保您使用的是“属性访问”而不是“字段访问”;即注释 getXXX 方法,而不是字段。在这个简单的示例中,您可能只有initialactual 的数据库列,因此difference 将被注释为@Transient
  • 您可能应该为difference 公开一个ReadOnlyDoubleProperty,因为它是绑定的(例如,您希望避免客户端代码调用differenceProperty().set(...))。
  • 哪个部分不工作?你没有得到正确的价值,或者你没有得到任何价值?在Productos 中,如果您使用precioProducto 的绑定,那么第45 行是无用的,因为值是根据这两个属性更新的。然后您可以简单地对其进行初始化,而无需设置初始值。之后,更新应该基于该绑定工作。我看到您将某个百分比之王设置为初始值(?)。你期待那里的百分比吗?然后您应该修改该绑定以表示该计算。
【解决方案2】:

已解决

步骤:

  1. 使用属性访问而不是字段访问。有关详细信息,请参阅此post,您也可以使用this gists 作为示例。
  2. 完成第 1 步后,您可以在需要计算的列中使用此代码(根据您的需要调整代码)。我从这个question 得到了这个想法。

        colDiferencia.setCellValueFactory((cellData) -> {
        cellData.getValue().DiferenciaExistenciaProperty()
                .bind(cellData.getValue().ProductosExistenciaActual().subtract(
                        Double.valueOf(String.valueOf(cellData.getValue().ProductosExistenciaInicialProperty()))));
        return cellData.getValue().DiferenciaExistenciaProperty().asObject();
    });
    
    colExistenciaF.setCellFactory((d) -> {
        TableCell<Productos, Double> cell = new TableCell<Productos, Double>() {
            @Override
            protected void updateItem(Double item, boolean empty) {
                super.updateItem(item, empty);
                setText(String.valueOf(item));
            }
    
        };
        return cell;
    });
    

使用这种方法你会解决问题,但我很确定你会像我一样遇到一些其他错误或问题。

现在我可以结束这个问题了,机器人,在感谢所有参与的人之前。

非常感谢。 @James_D 和@Sunflame 希望你们能看到我的练习项目并帮助我提高更多呵呵!再次感谢。

【讨论】: