J. Pichardo
J. Pichardo

Reputation: 3115

No inference in Generic Callback JavaFX

I have a TextFieldTableCell<Item,String> that I need to validate, therefore I can't use the usual way of

column.setCellFactory(TextFieldTableCell.forTableColumn());

So my intention was to do something like

column.setCellFactory(param -> {
    TableCell<Item,String> cell = TextFieldTableCell.forTableColumn().call(params);
    validate(validationRules, cell);
});

However it says that

CallbackTableColumn<Object,String>,TableCell<Object,String> cannot be 
applied to TableColumn<Item,String>

I get that, what I don't get is should it infer the type instead of Object

The only workaround I've found is to define a new StringConverter<String> which seems a little obnoxious.

new StringConverter<String>() {
            @Override
            public String toString(String object) {
                return object;
            }

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

Upvotes: 0

Views: 186

Answers (2)

James_D
James_D

Reputation: 209418

By chaining the two method calls (TextFieldTableCell.forTableColumn() and call()), you don't ever specify the actual type of the return of the first method, so the compiler doesn't have a chance to infer the type that should be returned from that method call.

If you want the compiler to infer this, you could do

Callback<TableColumn<Item, String>, TableCell<Item, String>> callback = TextFieldTableCell.forTableColumn();
TableCell<Item, String> cell = callback.call(param);

Of course, this is far more verbose than just specifying the type to the generic method forTableColumn directly:

TableCell<Item, String> cell = TextFieldTableCell.<Item>forTableColumn().call(param);

All of this seems a bit artificial, though. You are implementing a callback, and since TextFieldTableCell has appropriate constructors available, there is no need to go through an intermediate Callback. You can just do:

column.setCellFactory(col -> {
    TextFieldTableCell<Item, String> cell = new TextFieldTableCell<>();
    validate(validationRules, cell);
    return cell ;
});

or, if you need to specify a converter:

StringConverter<String> converter =  ... ;
column.setCellFactory(col -> {
    TextFieldTableCell<Item, String> cell = new TextFieldTableCell<>(converter);
    validate(validationRules, cell);
    return cell ;
});

For a default converter, you can just use

TextFieldTableCell<Item, String> cell = 
    new TextFieldTableCell<>(TextFormatter.IDENTITY_STRING_CONVERTER);

Upvotes: 1

Pavlo Viazovskyy
Pavlo Viazovskyy

Reputation: 937

You need to implicitly specify column type used in call to forTableColumn():

TableCell<Item,String> cell = TextFieldTableCell.<Item>forTableColumn().call(param);

If you will look at forTableColumn() JavaDoc, you'll see that it depends on generic type S which is type of elements in your TableView. If not specified, Object type is used which causes problems when you try to assign it to TableCell<Item,String> cell.

Upvotes: 1

Related Questions