Hi Marius, all,

And the biggest problem is the traversal logic. Finding the next
> editable cell is not easy. We need to check if the concrete cell is
> editable, the row, the table and the column.
> I implemented it by trying to edit a cell position and check if it
> 'worked' (we have an editing cell). We might be able to implement a
> somewhat more smart approach in the JFX internals.
> In any case, this is indeed a good follow up at one point.
>

I fully agree. The solution I implemented is brittle (that's what I think)
and having a proper solution with JavaFX internals would be way better.
Once we start discussing such an enhancement I'd be happy to show how I
solved it.

-- Daniel



>
> -- Marius
>
> Am 18.03.2026 um 12:05 schrieb Daniel Peintner:
> > Hi Marius and all,
> >
> > Thank you for your extensive work on this. Regarding PR #1935, I have
> > had the opportunity to test the changes, and the functionality for
> > committing values on focus loss appears to be working well.
> > I would like to share a few common use cases we encounter when working
> > with TableView in JavaFX:
> >
> > - Cell Traversal: When a cell is in editing mode and the user presses
> > "Tab," the subsequent cell should immediately enter editing mode (or
> > Alt+Tab the other direction).
> > - Selective Traversal: The ability to navigate through editable cells
> > while skipping read-only cells for example
> > - Editing Flow: F2 or a double-click should only be required for the
> > initial entry into editing mode. Subsequently, the user should be able
> > to navigate between cells and edit them directly (with keyboard only).
> >
> > We currently have a solution that "works" (the attached video might
> > give a better idea what I mean), but I believe developers often expect
> > this functionality to be available out of the box. While PR #1935 is a
> > significant step forward, we may want to consider additional features
> > to support these specific workflows.
> >
> > I am interested to hear your thoughts and if others agree that these
> > additions would be beneficial.
> >
> > Best regards,
> >
> > -- Daniel
> >
> >
> > 2026-03-18 11-40-34.gif
> >
> >
> > On Sat, Nov 15, 2025 at 5:27 PM Marius Hanl <[email protected]> wrote:
> >
> >     Hey all,
> >     I did a lot of focus tests the last weeks and wrote a big sampler
> >     application as well.
> >     I will provide the source code as Gist in the PR description at
> >     one point.
> >     First of all, things look pretty good! There are some problematic
> >     cases, and at least one bug from what I can see.
> >     Note: All the problematic cases below also affect all other
> >     Controls that commit their value on focus loss, like DatePicker,
> >     Spinner, ...
> >
> >     What works:
> >     - By default, the focus loss commit works well with all Controls
> >     out of the box
> >     - Mnemonics work. They will first request focus before they
> >     trigger the action
> >     Problematic cases:
> >     - A Tab selection change is fired before the focus is requested on
> >     the TabPane. While the focus lost commit still works, it is in my
> >     opinion too late. Think about disabling a Tab when something in a
> >     Table is invalid (which we know after the commit)
> >     - List/Tree/Table/View: Selection and focus is changed before the
> >     actual cell container will receive the focus. Even more weird: For
> >     both Tables, the selection change is fired BEFORE the focus
> >     change. List- and TreeView have the correct order. Again, in case
> >     we want to disable this Control when another Table is invalid,
> >     which we know right at the commit, we will still first trigger a
> >     selection and focus change
> >     Buggy cases:
> >     - As John also mentioned, non focus traversable Controls are
> >     completely broken. A non focus traversable Button or CheckBox will
> >     not request any focus. Therefore, Cells, DatePicker, ... can not
> >     commit their value. Other Controls set to non focus traversable
> >     like TextField or the TextField inside the DatePicker will request
> >     focus, the DatePicker button will not. This seems like a bug to
> >     me. Could also be something we want to ignore, as we can say: In
> >     this case, all focus loss commits are broken, so it is up to you.
> >     Feedback welcome
> >     Other cases:
> >     - MenuBar, Menu, MenuItem will not trigger focus at all. This
> >     might be expected. I don't know what to think about that. Feedback
> >     welcome
> >     -- Marius
> >     *Gesendet: *Freitag, 24. Oktober 2025 um 06:58
> >     *Von: *"Marius Hanl" <[email protected]>
> >     *An: *[email protected], [email protected],
> >     [email protected]
> >     *Betreff: *Re: Re: Re: Allowing a cell to commit the value on
> >     focus loss
> >     Those are good points. I will have a look. I do agree that the
> >     focus traversable behavior is questionable.
> >     I would expect that those problems also exist for Controls like
> >     the DatePicker, since it does also commit its value on focus loss.
> >
> >     We might not be able to 'fix' mnemonics focus loss, in this case
> >     the responsibility is indeed an application responsibility.
> >     -- Marius
> >     *Gesendet: *Mittwoch, 15. Oktober 2025 um 18:52
> >     *Von: *"John Hendrikx" <[email protected]>
> >     *An: *"Andy Goryachev" <[email protected]>, "Marius Hanl"
> >     <[email protected]>, "[email protected]"
> >     <[email protected]>
> >     *Betreff: *Re: [External] : Re: Allowing a cell to commit the
> >     value on focus loss
> >
> >     There is also the focus traversable flag that interacts with this,
> >     but perhaps there is a bug.  When a button has focusTraversable
> >     set to false, clicking it will not give it focus.  One may say
> >     that a property named "focus traversable" would only affect focus
> >     *traversal* with the keyboard (as I'd hardly call clicking with
> >     the mouse "traversal").
> >
> >     That still leaves mnemonic short-cuts and default actions for
> >     buttons though.  Pretty sure those also don't focus the button and
> >     aren't intended to, yet do execute the action.
> >
> >     --John
> >
> >     On 15/10/2025 17:20, Andy Goryachev wrote:
> >
> >          *
> >             Buttons are one of those (either with mouse press or
> >             keyboard short cut)
> >
> >         This looks like a bug to me, really.  What is the main purpose
> >         of the focus subsystem?
> >         I know we like to reinvent the wheel, but focus in Swing works
> >         as expected, and one does get focus lost event on mouse press,
> >         and the target button gets the focus. Why should FX be different?
> >         -andy
> >         *From: *John Hendrikx <[email protected]>
> >         <mailto:[email protected]>
> >         *Date: *Wednesday, October 15, 2025 at 08:05
> >         *To: *Marius Hanl <[email protected]>
> >         <mailto:[email protected]>, Andy Goryachev
> >         <[email protected]>
> >         <mailto:[email protected]>, [email protected]
> >         <[email protected]> <mailto:[email protected]>
> >         *Subject: *[External] : Re: Allowing a cell to commit the
> >         value on focus loss
> >
> >         Hi Marius,
> >
> >         Focus lost is currently sort of a proxy of starting an
> >         interaction with a new control, but not all controls gain
> >         focus when interacted with.  Buttons are one of those (either
> >         with mouse press or keyboard short cut), but there is I think
> >         also the scroll wheel that can interact with a control without
> >         focusing it (and perhaps even popup menu's).
> >
> >         I can only think of one half-baked solution to this:
> >
> >         - Have a new Event type that is always targetted at the
> >         current focus owner ("InterestLostEvent" ? :))
> >         - This event is automatically fired by Scene just before an
> >         event is fired that is not targetted at the current focus
> >         owner, AND the last event fired did have the focus owner as
> target
> >
> >         What would happen in practice then would be something like:
> >
> >         - User edits field, keypress events go to current focus owner
> >         - User does something else (moves mouse, scrolls, presses a
> >         hotkey, or presses a button):
> >             - An InterestLostEvent is fired at the current focus owner
> >         BEFORE the new event is fired
> >             - The delayed new event is now fired
> >             - No further InterestLostEvents are fired until the focus
> >         owner has received a normal event again
> >         - User goes back to editing after playing with the mouse;
> >         events targetted at the focus owner renew the interest in that
> >         control, and so next time an InterestLostEvent is fired again
> >         when needed
> >
> >         It feels a bit awkward, especially because simple things like
> >         mouse moves may trigger it already (but a mouse move may
> >         trigger something that requires the model to be up to
> >         date...); perhaps it would need to be selective in some way so
> >         one can choose to only be interested in the InterestLostEvent
> >         on focus loss and mouse clicks.
> >
> >         I can immediately see some problems as well.  Some controls I
> >         think allow editing without focus gain/loss at all (I think
> >         some controls can be edited by just scrolling the mouse wheel
> >         over them).  When should those controls "commit" their values...?
> >
> >         --John
> >
> >         On 15/10/2025 16:39, Marius Hanl wrote:
> >
> >             Hi John,
> >             you are right that there might be corner cases. I hope
> >             that we could, what Andy suggests, find all cases and have
> >             a deeper look at them.
> >             We can also check whether the focus delegation API from
> >             Michael is something that could help us here (but might be
> >             completely unrelated).
> >             The other options as you also mentioned, also have their
> >             problems. Even debouncing a commit on every keystroke can
> >             be unreliable if the user is too fast.
> >             I really hope we can make the focus loss reliable, as we
> >             then do not need much of an API changes inside the Cell
> >             Framework.
> >             -- Marius
> >             *Gesendet: *Montag, 13. Oktober 2025 um 19:32
> >             *Von: *"Andy Goryachev" <[email protected]>
> >             <mailto:[email protected]>
> >             *An: *"John Hendrikx" <[email protected]>
> >             <mailto:[email protected]>,
> >             "[email protected]" <mailto:[email protected]>
> >             <[email protected]> <mailto:[email protected]>
> >             *Betreff: *Re: Allowing a cell to commit the value on
> >             focus loss
> >             I wonder if we should find out exactly why onFocusLost
> >             does not work in these cases, as expected.  Then, if I
> >             understand the proposal correctly, we won't need any API
> >             changes.
> >             -andy
> >             *From: *openjfx-dev <[email protected]>
> >             <mailto:[email protected]> on behalf of John
> >             Hendrikx <[email protected]>
> >             <mailto:[email protected]>
> >             *Date: *Monday, October 13, 2025 at 07:17
> >             *To: *[email protected] <[email protected]>
> >             <mailto:[email protected]>
> >             *Subject: *Re: Allowing a cell to commit the value on
> >             focus loss
> >
> >             Hi Marius,
> >
> >             This may be unrelated, but it may be problematic to rely
> >             on committing values using focus lost:
> >
> >             I've built a lot of code that relies on focus lost to
> >             "commit" values to some underlying model.  However, I
> >             noticed that a focus lost handler for committing values is
> >             insufficient when an action is triggered that doesn't
> >             trigger a loss of focus.   For example, if I have a field
> >             "email address" and a Button "Send Email", and I have a
> >             focus lost handler to commit the email address textfield
> >             to an underlying model, then pressing the Button will not
> >             trigger that handler and the underlying model may not have
> >             been updated with the latest edits.
> >
> >             Solutions to trigger the correct action are all a bit
> >             tricky or annoying:
> >
> >             - Query all fields for their current contents as focus
> >             lost is not entirely reliable for this purpose
> >             - Have fields update models immediately (which would be on
> >             every key press...) -- this is not very efficient, and can
> >             get in the way of validation / model restrictions
> >             - Have controls listen to a "COMMIT" event (this is fired
> >             at the current focus owner by the Button).  This event may
> >             be veto'd if committing the value resulted in a validation
> >             error, in which case the button press is cancelled
> >
> >             I don't like any of these, but using the last option at
> >             the moment because I like constant updates and having to
> >             requery UI components even less...
> >
> >             --John
> >
> >
> >             I noticed however that if you edit some field (it doesn't
> >             have to be in a table view, just a regular field), and
> >             have a focus lost handler that commits the value, that
> >             this focus lost handler is insufficient...
> >
> >             On 13/10/2025 14:53, [email protected] wrote:
> >
> >                 All,
> >                 I created an initial poc 1* to support developers to
> >                 commit the cell value when the focus is lost 2*
> >                 (including 3*).
> >                 More specifically, this gives the maximum flexibility
> >                 to choose what should happen when the focus is lost or
> >                 the editing index changed (which may happen when
> >                 clicking into another cell while editing).
> >                 All information mentioned here are also in the
> >                 description of the PR.
> >                 *API*
> >                 **
> >                 - Instead of calling `/cancelEdit/`, every cell now
> >                 calls `/stopEdit/` when the focus is lost or the
> >                 editing index changed. The default behavior is
> >                 cancelling the edit, but developers can now override
> >                 the behavior and allow a `/commitEdit/` instead
> >                 - There are multiple 'events' that can lead to a
> >                 editing change. Every change will now call `/stopEdit/`.
> >                 It is therefore the responsibility of the developer to
> >                 decide, when it makes sense to actually commit the
> >                 value instead of cancelling it. This decision was made
> >                 as the behavior is manipulating the editing index, but
> >                 you as a developer can as well. We do not really know
> >                 what intention led to e.g. a change of the editing index.
> >                 - Every `/MOUSE_PRESSED/` shifts the focus to the cell
> >                 container, which is undesired in case of editing the
> >                 cell. So this event is now consumed.
> >                 - All `/TextField/` cells now commit their value
> >                 (instead of cancel) on focus loss
> >                 - `/TextField/` Escape handling was badly implemented
> >                 (it was never really called, as the cell container
> >                 handled Escape before)
> >                 *Considerations*
> >
> >                 - I tried to make the API minimal, and without
> >                 breaking changes (other than the `/TextField/` cells
> >                 committing their values, but we may split this up)
> >                 - The Cell Container focus behavior is, well, weird
> >                 right now. That is why consuming the event is needed
> >                 to better support this PR. One thing we may can
> >                 consider is using the `/focusWithin/` property instead
> >                 for all 4 Cell Containers and not calling
> >                 `/requestFocus/` for nearly every `/MOUSE_PRESSED/`
> >                 event. If we decide so, this is needs to be done
> >                 before merging this PR.
> >                 - Clicking the `/ScrollBar/` now commits/cancels the
> >                 edit. I checked other applications and this is very
> >                 common. But something I need to note here. This
> >                 probably can be fixed in the same way mentioned above
> >                 (`/focusWithin/`)
> >                 - It might be hard for a developer to exactly know the
> >                 cause why `/stopEdit/` is called. This does not seem
> >                 like a problem, as e.g. for a `/TextField/`, you
> >                 normally register listeners for e.g. pressing the
> >                 Escape key on it, so you keep full control.
> >                 *Another Approach*
> >
> >                 - Another Approach I tested could be to request the
> >                 focus to a cell when clicked/edited, to ensure that
> >                 the focus listener is ALWAYS called before another
> >                 cell will reach the editing state. Again, we probably
> >                 need to change the focus handling to e.g. use the
> >                 `/focusWithin/` property. With this approach, we can
> >                 only call `/stopEdit` /when the focus changed (since
> >                 it is now called always), but not when the editing
> >                 index changed.
> >                 1* - https://github.com/openjdk/jfx/pull/1935
> >                 <
> https://urldefense.com/v3/__https://github.com/openjdk/jfx/pull/1935__;!!ACWV5N9M2RV99hQ!KeaTwOLaODiie2jQZ01j-vH00U9_nZNV8YxV6B0SXCExWnLFky0svIofyVK0ZPt0xawAISlouP_NCkqvMwFhYVHnQZte$
> >
> >                 2* - https://bugs.openjdk.org/browse/JDK-8089514
> >                 3* - https://bugs.openjdk.org/browse/JDK-8089311
> >                 -- Marius
> >
>

Reply via email to