1

I am trying to commit an edit when a JavaFX 8 TreeTableView cell loses focus. I see the question has already been asked, but I would like to understand why my attempt below does not work. More specifically, why a listener to the focusedProperty of the cell does not get invoked.

Item<String, Object> is my data representation, and is an extension of Map<String, Object>.

Essentially, I wrap the standard text cell factory within a new cell factory that uses the standard one to create a cell, and adds a listener to its focusedProperty. When focus is lost, I store the cell text on it.

However, printouts indicate the event listener is never invoked.

I added the listener to the cell's focusedProperty because I could not identity a method that gives me the text control directly. The getGraphic() method (which I read somewhere is a misnomer because it points to whatever node is in the cell) returns a null pointer.

Any idea why the listener is never invoked? Thanks.

// obtain usual cell factory for text editing
Callback<TreeTableColumn<Item<String, Object>, String>, TreeTableCell<Item<String, Object>, String>>
   callBackForTreeTableColumn = TextFieldTreeTableCell.forTreeTableColumn();

// create a new cell factory that delegates the cell creation to the standard factory
// and then adds a listener to cell's focusedProperty:
Callback<TreeTableColumn<Item<String, Object>, String>, TreeTableCell<Item<String, Object>, String>>
    callBackWithOnFocusedListener = new Callback<TreeTableColumn<Item<String, Object>, String>, TreeTableCell<Item<String, Object>, String>> () {

    @Override
    public TreeTableCell<Item<String, Object>, String> call(TreeTableColumn<Item<String, Object>, String> column) {
        TreeTableCell<Item<String, Object>, String> cell = callBackForTreeTableColumn.call(column);
        System.out.println(System.currentTimeMillis() + ": cell created!"); 
        cell.focusedProperty().addListener((obs, wasFocused, isNowFocused) -> {
            System.out.println(System.currentTimeMillis() + ": Focus changed!");    
            if (! isNowFocused) {
                System.out.println(System.currentTimeMillis() + ": Lost focus, going to commit!");  
                Item<String, Object> item = cell.getTreeTableRow().getTreeItem().getValue();
                item.put(header, cell.getText());
            }
        });
        return cell;
};
column.setCellFactory(callBackWithOnFocusedListener);
user118967
  • 4,895
  • 5
  • 33
  • 54
  • 1
    Possible duplicate of [How to enable commit on focusLost for TableView/TreeTableView?](http://stackoverflow.com/questions/24694616/how-to-enable-commit-on-focuslost-for-tableview-treetableview) – kleopatra Oct 29 '15 at 23:28
  • Like I mentioned in the text of the question, it is not a duplicate because I am not necessarily asking how to enable such commits, but asking why the particular event handler is not being invoked. – user118967 Oct 29 '15 at 23:50
  • 1
    ahh, I see - hard to tell without a SSCCE but my first guess would be that the _cell's_ focusedProperty is always false, it's either the contained textField or the table that have it set to true. Just guessing .. – kleopatra Oct 30 '15 at 10:28
  • Thanks! How can I access the textField, do you know? Couldn't find it. – user118967 Oct 30 '15 at 15:50
  • you did read the other question and the answers there, didn't you ;-) A listener to the focusproperty doesn't help in the underlying problem, so you don't need to access the textfield. If you insist: read the code of TextFieldTreeTableCell, textfield is not public but you can access it via getGraphic after it's first set (that is after an edit is first started) - by listening to the graphic property – kleopatra Oct 30 '15 at 16:15
  • btw: I still think this is a duplicate - from your comments it looks like your _real_ question is how-to-commit (which is addressed in the duplicate) – kleopatra Oct 30 '15 at 16:17
  • Fair enough, it is indeed very close, I am marking it as such. Thanks, sorry. – user118967 Oct 30 '15 at 20:02

1 Answers1

2

The short answer to why don't I see a change in the focusedProperty is that there is no change because the property is always false.

Reason being, that the focusedProperty of a Tree/Table/Cell is (arguably mis-) used to represent the focused cell of the Tree/TableView's FocusModel (vs. the "real" focus as being focusOwner), but only if cellSelectionEnabled.

The relevant code snippet in updateFocus (in TableCell) which is called f.i. by an InvalidationListener to the focusedProperty of the FocusModel:

private void updateFocus() {
    final boolean isFocused = isFocused();
    if (! isInCellSelectionMode()) {
        if (isFocused) {
            setFocused(false);
        }
        return;
    }
    ...
}  
kleopatra
  • 51,061
  • 28
  • 99
  • 211
  • Thanks. Are you sure cellSelectionEnabled and isInCellSelectionModel are in TableCell? Could not find them. Does your answer imply I can "fix" the problem by setting cellSelectionEnabled to true (once I find it)? – user118967 Oct 30 '15 at 15:57
  • it's a property of table's selectionModel. Generally, listener to the focusedProperty _does not_ work, see the duplicate. Didn't try with cellSelection (which most probably will interupt your ui too much anyway). BTW: I answered the "why", not the "how" - that's the duplicate part of your question ;-) – kleopatra Oct 30 '15 at 16:11