[External] : Re: Allowing a cell to commit the value on focus loss
John Hendrikx
john.hendrikx at gmail.com
Wed Oct 15 16:52:45 UTC 2025
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 <john.hendrikx at gmail.com>
> *Date: *Wednesday, October 15, 2025 at 08:05
> *To: *Marius Hanl <mariushanl at web.de>, Andy Goryachev
> <andy.goryachev at oracle.com>, openjfx-dev at openjdk.org
> <openjfx-dev at openjdk.org>
> *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" <andy.goryachev at oracle.com>
> *An: *"John Hendrikx" <john.hendrikx at gmail.com>,
> "openjfx-dev at openjdk.org" <openjfx-dev at openjdk.org>
> *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 <openjfx-dev-retn at openjdk.org> on behalf of
> John Hendrikx <john.hendrikx at gmail.com>
> *Date: *Monday, October 13, 2025 at 07:17
> *To: *openjfx-dev at openjdk.org <openjfx-dev at openjdk.org>
> *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, mariushanl at web.de 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
> 2* - https://bugs.openjdk.org/browse/JDK-8089514
> 3* - https://bugs.openjdk.org/browse/JDK-8089311
>
> -- Marius
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/openjfx-dev/attachments/20251015/e1412e15/attachment-0001.htm>
More information about the openjfx-dev
mailing list