Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

javafx tableview oneditcommit does not get called with custom cellfactory?

have a look the following working code:

    class MyType{
       SimpleStringProperty myname;
       SimpleObjectProperty<Color> mycolor;
    }

    TableColumn col;
    arr = FXCollections.observableArrayList(new ArrayList<MyType>());
    tblColName.setCellValueFactory(new PropertyValueFactory("myname"));
    // Use the cell-factory provided by TextFieldTableCell.
    tblColName.setCellFactory(TextFieldTableCell.forTableColumn());
    tblColName.setOnEditCommit(new EventHandler<TableColumn.CellEditEvent>() {
        @Override
        public void handle(TableColumn.CellEditEvent cellEditEvent) {
            ((MyType) cellEditEvent.getRowValue()).myname.set((String) cellEditEvent.getNewValue());
        }
    });

However, as soon as I am using a custom TableCell, the code in setOnEditCommit is not called anymore:

public class ColorPickerTableCell<S> extends TableCell<S, Color>{
private ColorPicker cp;

public ColorPickerTableCell(){        
    cp = new ColorPicker(Color.BLACK);        
    cp.setOnAction(new EventHandler<ActionEvent>() {
        @Override
        public void handle(ActionEvent event) {
            commitEdit(cp.getValue());
            updateItem(cp.getValue(), isEmpty());
        }            
    });                
    setGraphic(cp);
    setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
    setEditable(true);        
}     
@Override
protected void updateItem(Color item, boolean empty) {
    super.updateItem(item, empty);
    cp.setVisible(!empty);
    this.setItem(item);
}

public static <T> Callback<TableColumn<Color, T>, TableCell<Color, T>> forTableColumn(){
    return new Callback<TableColumn<Color, T>, TableCell<Color, T>>() {
        @Override
        public TableCell<Color, T> call(TableColumn<Color, T> colorTTableColumn) {
            return new ColorPickerTableCell();
        }
    };

}

}

A slight change of the code above...

    TableColumn col;
    arr = FXCollections.observableArrayList(new ArrayList<MyType>());
    tblColName.setCellValueFactory(new PropertyValueFactory("myname"));
    // Use the cell-factory provided by TextFieldTableCell.
    tblColName.setCellFactory(ColorPickerTableCell.forTableColumn());
    tblColName.setOnEditCommit(new EventHandler<TableColumn.CellEditEvent>() {
        @Override
        public void handle(TableColumn.CellEditEvent cellEditEvent) {
            throw new NotImplementedException(); // is never thrown.
        }
    });

... makes the code not work anymore. The exception is never thrown. I think that I am doing something wrong in the design of ColorPickerTableCell, but I cannot imagine what. How can I make JavaFX call my OnEditCommit ?

like image 842
Max Beikirch Avatar asked Dec 03 '25 06:12

Max Beikirch


2 Answers

You need first to go to edit state with statEdit(); , if you now commit an event will be fired

like image 144
justcode Avatar answered Dec 05 '25 18:12

justcode


I've recently had the same problem. Unfortunately, I haven't found any way of trigerring that event from the ColorPicker control. However, I came up with the following workaround.

First of all, I created a Color wrapper class:

public class ColorWrapper {

 private Color color;

 ....
}

I replaced the Color instance with the wrapper instance in my model class M. Next, I implemented setCellFactory method in the following way:

myColumn.setCellFactory(new Callback<TableColumn<M, ColorWrapper>, TableCell<M, ColorWrapper>>() {          

        @Override
        public TableCell<M, ColorWrapper> call(TableColumn<M,ColorWrapper> arg0) {
            return new TableCell<M, ColorWrapper>(){

                private ColorPicker colorPicker;

                private ColorPicker createPicker(){
                    colorPicker = new ColorPicker();

                    colorPicker.setOnAction(new EventHandler<ActionEvent>() {
                        @Override
                        public void handle(ActionEvent evt) {
                            ColorPicker cp = (ColorPicker)evt.getSource();
                            ColorWrapper cw = (ColorWrapper)cp.getUserData();
                            cw.setColor(cp.getValue());
                        }

                    });
                    return colorPicker;
                }


                @Override
                protected void updateItem(ColorWrapper value, boolean empty) {                      
                    super.updateItem(value, empty);
                    if(empty){
                        return;
                    }

                    if(colorPicker == null){
                        colorPicker = createPicker();
                        colorPicker.setUserData(value);
                    }

                    colorPicker.setValue(value.getColor());
                    setGraphic(colorPicker);
                }

            };

        }            

    });

As you can see, I just made use of setUserData/getUserData methods of the ColorPicker class and that's it. It works.