4

I've implemented a cell editor similar to EditingCell in Example 12-11 Alternative Solution Of Cell Editing from the JavaFX TableView tutorial (the issue I'm describing can be reproduced, using that example as an SSCCE).

However, it comes along with a very annoying bug, and that is that every mouse click (either for moving the caret, or selecting text) inside the TextEdit control used as the editor will cause a focus change, and thus commit and end the edit.

The code responsible for committing:

textField.focusedProperty().addListener(new ChangeListener<Boolean>(){
    @Override
    public void changed(ObservableValue<? extends Boolean> arg0,
                        Boolean arg1, Boolean arg2) {
        if (!arg2) {
            commitEdit(textField.getText());
        }
    }
});

I've been trying for hours looking through this with the debugger and reading source code, and I've found that the focus is temporary given to the TableView's VirtualFlow and then quickly back to the TextEdit again (not sure why this focus change happens, feel free to shed some light on that too). This happens faster than the UI updates, so users will not experience this quick focus change. Unfortunately, the change listener will...

How can I create a cell editor that does not have this issue?

Requirements:

  • I need to have the editor commit values on "real" focus changes (ie. click outside the editor)
  • Clicks inside the editor must propagate to the TextEdit to allow text selection, moving the caret etc.
  • It should work with Java 7 and JavaFX 2.2

PS: The solution mentioned in this blog post (and its update) shows the exact same issue.

Harald K
  • 26,314
  • 7
  • 65
  • 111
  • Your lucky. I use the exact same code and my focus changed listener never even fires. 1.8 b109 here. What's your version? – brian Jan 30 '14 at 14:21
  • @brian And I was hoping upgrading might help.. :-P I'm using Java 7 + JavaFX 2.2 – Harald K Jan 30 '14 at 17:11
  • 1
    I just tried b127 and it works if I tab away from the cell or click outside the table. If I click inside the table, the edit is discarded. I think that the problem is that mouse down selects a new cell and cancels editing before the focus changed event fires. If I step into the source in TableCell.java, commitEdit just returns because of a !isEditing() check. – brian Feb 02 '14 at 20:54
  • Hmmm... Maybe it would be possible to override `TableView.edit` to get around it? In any case, I'm a little disappointed with the maturity of table editing in FX so far (not that it was ever fantastic in Swing, but it could be made to work). I've been testing out the answer given in [this question](http://stackoverflow.com/q/7880494/1428606), and it seems very interesting. – Harald K Feb 02 '14 at 21:14
  • That sample you linked to in the comments has no way of canceling the edit. Other than that, it's pretty. I've added a mouse pressed event filter for the table. If the table is in an editing state I just consume the event. This prevents clicking away from a cell to another table cell. You can still tab or click another control and the focus changed event fires and commits the edit. – brian Feb 03 '14 at 04:34

1 Answers1

1

This problem appears fixed in 1.8b123.

If you need it to work in FX 2.2, try this super-ugly hack:

            public void changed(ObservableValue<? extends Boolean> arg0, 
                Boolean arg1, Boolean arg2) {
                    if (!arg2) {
                        final PauseTransition wait = new PauseTransition(Duration.millis(20));
                        wait.setOnFinished(new EventHandler<ActionEvent>() {
                            @Override
                            public void handle(ActionEvent event) {
                                if (! textField.isFocused()) {
                                    commitEdit(textField.getText());          
                                }
                            }
                        });
                        wait.play();
                    }
            }
James_D
  • 201,275
  • 16
  • 291
  • 322
  • Many thanks! Unfortunately, it doesn't always work. It seems to work as long as I'm clicking on (as in giving focus to) a control outside the table. If I click on a different row/column in the table, the change isn't committed (or committed too late, probably). – Harald K Jan 31 '14 at 08:58