在JavaFX中呈现TableColumns的通用方法

在JavaFX中呈现TableColumns的通用方法,java,javafx,tableview,Java,Javafx,Tableview,因此,我的应用程序在不同的FXMLViewController中使用多个TableView来表示多个不同的JPA实体。以下示例适用于JobSupplierParts /** * renderDoubleColumn takes a TableColumn setting its value and type before setting up edit event handling. * @param column the tableColumn to be set up. * @

因此,我的应用程序在不同的FXMLViewController中使用多个TableView来表示多个不同的JPA实体。以下示例适用于JobSupplierParts

    /**
 * renderDoubleColumn takes a TableColumn setting its value and type before setting up edit event handling.
 * @param column the tableColumn to be set up.
 * @param field the name of the field to be mapped to.
 * @param methodName the set method name of the field.
 */
protected void renderDoubleColumn(TableColumn<JobSupplierPart, Double> column, String field, String methodName) {
    String className = "BiasDB.JobSupplierPart";
    column.setCellValueFactory(new PropertyValueFactory<>(field));
    column.setCellFactory(TextFieldTableCell.<JobSupplierPart, Double>forTableColumn(new DoubleStringConverter()));
    column.setOnEditCommit(
            new EventHandler<TableColumn.CellEditEvent<JobSupplierPart, Double>>() {
                @Override
                public void handle(TableColumn.CellEditEvent<JobSupplierPart, Double> t) {
                    JobSupplierPart supplierPart = t.getTableView().getItems().get(t.getTablePosition().getRow());

                    try {
                        Class<?> c = Class.forName(className);
                        Method method = c.getDeclaredMethod(methodName, Double.class);
                        method.invoke(supplierPart, t.getNewValue());
                        supplierPart.setTotal(updateItem(supplierPart));
                    } catch (ClassNotFoundException|NoSuchMethodException|IllegalAccessException|InvocationTargetException ex) {
                        logger.error("renderDoubleColumn",ex);
                    } //End try to get method from String.

                    try {
                        jobSupplierPartController.edit(supplierPart);
                    } catch (Exception ex) {
                        logger.error("renderDoubleColumn",ex);
                    }
                    t.getTableView().refresh();
                }
            } //END Event Handler
    ); //END SetOnEditCommit.
}
//END renderDoubleColumn

但是-我必须为每个JPA实体创建新方法。是否有可能替换对JobSupplierPart的引用,使其成为一个通用方法,就像我用这些方法实现的那样?我尝试了T或K等选项,但都返回了错误。控制器只能作为参数传递。或者这真的是一个糟糕的做法/性能低下的事情吗?

所以我不知道Java爱好者是否会同意这个解决方案,但作为对我能够使代码更干净后不久发布并删除的答案的回应。我还将“设置/编辑”部分移动到了一个方法中,因此现在我有:

/**
 * renderBigDecimalColumn takes a TableColumn setting its value and type before setting up edit event handling.
 * @param column the tableColumn to be set up.
 * @param field the name of the field to be mapped to.
 */
private void renderBigDecimalColumn(TableColumn<AccountAsset, BigDecimal> column, String field) {

    //Set an observable value for the column
    column.setCellValueFactory(new PropertyValueFactory<>(field));

    //Set how we want the cell to be rendered
    // This line varies for the different cell types e.g. Strings, Bools etc.
    column.setCellFactory(TextFieldTableCell.<AccountAsset, BigDecimal>forTableColumn(new BigDecimalStringConverter()));

    //Set how we want the cell to be edited including the row update.
    column.setOnEditCommit(t -> {
        handleEditCommit(t, field);
    }); //END SetOnEditCommit.

} //END renderBigDecimalColumn
/**
*renderBigDecimalColumn在设置编辑事件处理之前接受TableColumn设置其值和类型。
*@param column要设置的tableColumn。
*@param field要映射到的字段的名称。
*/
私有void renderBigDecimalColumn(TableColumn列,字符串字段){
//设置列的可观察值
column.setCellValueFactory(新属性ValueFactory(字段));
//设置单元格的渲染方式
//该行因不同的单元格类型而不同,例如字符串、布尔等。
column.setCellFactory(TextFieldTableCell.forTableColumn(新的BigDecimalStringConverter());
//设置编辑单元格的方式,包括行更新。
column.setOnEditCommit(t->{
handleEditCommit(t,字段);
});//结束SetOnEditCommit。
}//END renderBigDecimalColumn
我的handleEditCommit方法如下所示:

/** handleEditCommit deals with updating and saving the new data from the table view.
 *
 * @param t
 * @param field
 */
private void handleEditCommit(javafx.scene.control.TableColumn.CellEditEvent<AccountAsset,?> t, String field) {
    AccountAsset rowData = t.getTableView().getItems().get(t.getTablePosition().getRow());

    //Set the new value.
    try {
        BeanUtils.setProperty(rowData, field, t.getNewValue());
    } catch (IllegalAccessException | InvocationTargetException ex) {
        logger.error("handleEditCommit / Setter", ex);
    }

    //Save the new rowData back to the database.
    try {
        tableDataController.edit(rowData);
    } catch (Exception ex) {
        logger.error("handleEditCommit / Edit", ex);
    }
}
/**handleEditCommit处理更新和保存表视图中的新数据。
*
*@param t
*@param字段
*/
私有void handleEditCommit(javafx.scene.control.TableColumn.CellEditEvent t,字符串字段){
AccountAsset rowData=t.getTableView().getItems().get(t.getTablePosition().getRow());
//设置新值。
试一试{
setProperty(rowData,field,t.getNewValue());
}捕获(IllegalAccessException | InvocationTargetException ex){
logger.error(“handleEditCommit/Setter”,ex);
}
//将新的行数据保存回数据库。
试一试{
tableDataController.edit(行数据);
}捕获(例外情况除外){
logger.error(“handleEditCommit/Edit”,ex);
}
}

这是非常糟糕的代码(在非常正常的上下文中使用反射,调用table.refresh)-为什么你想与fx作斗争?@kleopatra。你想扩大业务吗。我渴望学习。在进入Python和PHP 13年后,刚刚回到Java。为什么你不遵循干巴巴的原则,拥有一个方法,而不是许多相同的方法,除了几个名称上的改变外。@kleopatra。嗨,我不知道你是否会觉得我现在发布的答案没有那么糟糕——我希望如此!从Java8开始,您可以使用方法引用,它比基于字符串的字段名更不容易出错,并提供编译时检查(类型、名称、访问等)。对getter使用
回调
函数
,对setter使用
BiConsumer
,并传递例如
AccountAsset::getDiscount
AccountAsset::setDiscount
。。。如果您有FX样式的属性,则只需传递属性getter即可。
/** handleEditCommit deals with updating and saving the new data from the table view.
 *
 * @param t
 * @param field
 */
private void handleEditCommit(javafx.scene.control.TableColumn.CellEditEvent<AccountAsset,?> t, String field) {
    AccountAsset rowData = t.getTableView().getItems().get(t.getTablePosition().getRow());

    //Set the new value.
    try {
        BeanUtils.setProperty(rowData, field, t.getNewValue());
    } catch (IllegalAccessException | InvocationTargetException ex) {
        logger.error("handleEditCommit / Setter", ex);
    }

    //Save the new rowData back to the database.
    try {
        tableDataController.edit(rowData);
    } catch (Exception ex) {
        logger.error("handleEditCommit / Edit", ex);
    }
}