<!DOCTYPE html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  </head>
  <body>
    <p>This should certainly also become possible at some point.  There
      already is internal API to find the next/previous or left/right
      Node, it is more a question how to expose this as an API at this
      point.</p>
    <p>For this specific case, you'd probably want to change focus in an
      ActionEvent, or possibly a KeyEvent handler that looks for ENTER.</p>
    <p>Then in the handler you'd probably just want to ask Scene to move
      focus to the logical next Node.  When in an event handler, that
      could be something like:</p>
    <p>      oneOfMyNodes.getScene().focusNext();</p>
    <p>or:</p>
    <p>      oneOfMyNodes.getScene().focus(Direction.NEXT);</p>
    <p>From what I can see, these methods would be trivial to add to
      Scene, as all the traversal methods are already present there.  I
      also think that it would be the correct place to have them, as
      there is no focus without a Scene and Scene already has the
      focusOwner property.</p>
    <p>Currently this all is already possible for the user, but you'd
      need to build your own util that finds the next Node (there are
      some simple rules for this, like finding the current child index
      in the parent, going up the stack of parents when on the last
      child, etc... I think I may have it somewhere in a utility already
      :))<br>
    </p>
    <p>--John<br>
    </p>
    <p><br>
    </p>
    <div class="moz-cite-prefix">On 19/09/2024 20:30, Chuck Davis wrote:<br>
    </div>
    <blockquote type="cite"
cite="mid:CAHf=Y_b_dLzvmbjRLO+c+jmQHDfN4zdFcpDxhMW_TdiUNiZw4w@mail.gmail.com">
      <meta http-equiv="content-type" content="text/html; charset=UTF-8">
      <div dir="ltr">
        <div>Focus traversal in JavaFX is one of the two things I miss
          most about Swing.  With Swing we could access the policy and
          move to the next or previous object programmatically -- a
          feature that is sadly lacking in FX.  For those of us old
          enough to remember the good old days of character interfaces,
          hitting the enter key was the way to move to the next input
          field.  I still maintain that feature but I've had to write
          all the code myself and for each field it has to be hard coded
          -- a real nuisance and totally unnecessary if we could access
          the TraversalPolicy and call next() or previous() like we did
          in Swing.</div>
        <div><br>
        </div>
        <div>For example, place characters in a TextField and hit the
          enter key to trigger an event.  Execute the method to process
          the verification, conversion, formatting and then
          TraversalPolicy.next() places focus on the next input field --
          good old efficient input and finger action.  No unnecessary
          and inefficient hand movements.<br>
        </div>
        <div><br>
        </div>
        <div>My $.02 on this whole discussion in this and associated
          threads regarding addressing the FX TraversalPolicy.<br>
        </div>
      </div>
      <br>
      <div class="gmail_quote">
        <div dir="ltr" class="gmail_attr">On Thu, Sep 19, 2024 at
          8:39 AM John Hendrikx <<a
            href="mailto:john.hendrikx@gmail.com" moz-do-not-send="true"
            class="moz-txt-link-freetext">john.hendrikx@gmail.com</a>>
          wrote:<br>
        </div>
        <blockquote class="gmail_quote"
style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">I've
          been looking into how exactly navigation keys are being used
          in FX, <br>
          and who is responsible for handling them:<br>
          <br>
          - Controls can choose to install navigational keys directly in
          their <br>
          input map (using
          FocusTraversalInputMap::getFocusTraversalMappings)<br>
          - Controls can choose to do nothing and leave navigation keys
          to bubble <br>
          up to Scene, at which point Scene will act on any unconsumed
          navigation <br>
          keys (in the same was as the traversal mappings would)<br>
          <br>
          Scene basically is capable of almost all navigation you could
          possibly <br>
          want out of the box.  Any control that does not install
          navigation keys, <br>
          and leaves said keys to bubble up gets navigation for
          **free**.  This is <br>
          almost all controls in JavaFX, and it makes sense as Controls
          should not <br>
          care about navigation, they should only care about key presses
          that <br>
          affect them directly.  Navigation should be a concern
          somewhere higher <br>
          up in the hierarchy.<br>
          <br>
          So why do some controls install their own navigation keys?<br>
          <br>
          There are two answers:<br>
          <br>
          1. For some controls, navigation is conditional. A Spinner
          only allows <br>
          directional navigation for the left/right keys, or up/down
          keys <br>
          depending on its orientation.<br>
          2. There is an unfortunate choice in ScrollPane that consumes
          <br>
          directional keys for scrolling purposes, and so if such keys
          were left <br>
          to bubble up, they would not end up at Scene.  Any control
          supporting <br>
          directional navigation therefore must **specifically** install
          these <br>
          bindings directly, even though navigation is not their concern
          (a Button <br>
          cares about being pressed, not about activating unrelated
          controls nearby).<br>
          <br>
          The ScrollPane eating directional keys is an odd choice. In
          order for it <br>
          to do so one of the following must be true:<br>
          <br>
          - A control inside it has focus that should act on directional
          <br>
          navigation, but forgot to install navigation bindings (a
          custom <br>
          control).  Such a control would work perfectly when not part
          of a <br>
          ScrollPane (as Scene would then handle directional
          navigation), but <br>
          break when placed inside it.  Note that all JavaFX controls do
          this <br>
          "properly".  I couldn't find any controls that would leave
          directional <br>
          keys to bubble up for a ScrollPane to consume.<br>
          <br>
          - The ScrollPane itself has focus; this can only happen when
          directly <br>
          selected with the mouse (or focus traversable is set to true)
          and no <br>
          specific control inside the pane was selected.  The ScrollPane
          receives <br>
          the ":focused" style, clearly indicating that it is the target
          for <br>
          keyboard events to the user.<br>
          <br>
          In short, ScrollPane is making navigation a lot more complex
          within FX <br>
          than it needs to be.  Especially custom controls that do not
          have access <br>
          (currently) to install navigational bindings will suffer from
          this, and <br>
          will have to resort to their own navigation implementation for
          <br>
          directional keys when placed inside a ScrollPane.<br>
          <br>
          # Proposal<br>
          <br>
          I think ScrollPane violates what I think should be a
          fundamental rule.  <br>
          Keys should only be consumed by what the user perceives as the
          focused <br>
          control (ie. the one outlined with a highlighted border), with
          the only <br>
          exceptions being short cuts (from a menu) or mnemonics. 
          Containers such <br>
          controls happen to be placed in should NOT consume key events
          -- the <br>
          container is not the control with the focus, and so would
          confuse the <br>
          user.  Only ScrollPane is violating this currently.  Note that
          if the <br>
          ScrollPane has focus itself (and it has the :focused
          highlight) then it <br>
          is perfectly fine and expected for it to consume keys as much
          as it wants.<br>
          <br>
          This is why I think we should modify ScrollPane to not consume
          the <br>
          directional keys, unless it specifically has the focus.  All
          other <br>
          controls can then remove their navigational bindings and leave
          them to <br>
          bubble up to Scene, cleaning up their behaviors so they can
          focus on <br>
          other concerns.  Custom controls would no longer need to
          install <br>
          navigational bindings either, and would not need to worry
          about being <br>
          placed inside a ScrollPane and having their directional
          navigation broken.<br>
          <br>
          Optional, but recommended, controls like Spinner should only
          act on the <br>
          directional keys intended for them, and leave the ones they
          can't use to <br>
          bubble up.  So a vertical spinner would consume up/down for
          changing the <br>
          spinner value, but would leave left/right untouched for Scene
          to <br>
          handle.  Controls that install a full set of navigational keys
          (like <br>
          Button, ListView and TitledPane) don't need to do so anymore.<br>
          <br>
          I think I will file a ticket for this soon, but I'm curious
          what others <br>
          think of this analysis.<br>
          <br>
          Note that by solving this problem, the need to make navigation
          <br>
          functionality available to custom controls severely diminishes
          as one <br>
          can simple leave the KeyEvents responsible for standard
          navigation to <br>
          bubble up (recommended as this may be different for each
          platform).<br>
          <br>
          --John<br>
          <br>
        </blockquote>
      </div>
    </blockquote>
  </body>
</html>