[prev in list] [next in list] [prev in thread] [next in thread] 

List:       openjdk-openjfx-dev
Subject:    Re: Node.lookupAll behaves differently before Scene is shown
From:       Scott Palmer <swpalmer () gmail ! com>
Date:       2022-12-25 17:51:21
Message-ID: 24068185-D7DE-47F8-B2F1-5DD66DFB6636 () gmail ! com
[Download RAW message or body]

[Attachment #2 (text/html)]

<html><head><meta http-equiv="content-type" content="text/html; \
charset=utf-8"></head><body dir="auto">Items added to a control like ListView, \
TableView, TreeView, are of an arbitrary type and are rendered via a CellFactory, not \
added as Nodes. &nbsp;(And in fact, as recent clarifications to the Javadoc mention, \
Nodes as items in the lists are strongly discouraged.). The items of a SplitPane are \
explicitly Nodes. So it isn't quite the same, but I get your \
point.<div><br></div><div>I think if anything a clarification in the Javadoc would \
help. &nbsp;I suspect changing the behaviour of lookup/lookupAll might be more \
problem than it is worth.</div><div><br></div><div>In my application, I've worked \
around the issue by deferring the call until the CSS has been applied through the \
usual flow, but I can confirm that explicitly calling applyCss() is also a valid \
workaround.</div><div><br><div dir="ltr">Scott</div><div dir="ltr"><br><blockquote \
type="cite">On Dec 24, 2022, at 7:05 PM, John Hendrikx \
&lt;john.hendrikx@gmail.com&gt; wrote:<br><br></blockquote></div><blockquote \
type="cite"><div dir="ltr">  
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  
  
    <p>One thing you could try still, whether acceptable or not, is to
      call `applyCss` on the border pane before calling the count
      function.</p>
    <p>As for the "and any children", I'm not sure how you should
      interpret that.&nbsp; For a SplitPane, the nodes that are part of it
      are in the items list (you don't add them as actual children).&nbsp;
      The example in split pane also does something like
      `splitPane.getItems().addAll(x, y, z)`. <br>
    </p>
    <p>Same may apply to items in a List / Table / TreeView -- are they
      children?<br>
    </p>
    <p>--John<br>
    </p>
    <div class="moz-cite-prefix">On 24/12/2022 19:09, Scott Palmer
      wrote:<br>
    </div>
    <blockquote type="cite" \
cite="mid:3BF24C3E-D6C0-4610-972F-C7CFC7EEBECB@gmail.com">  <meta \
http-equiv="content-type" content="text/html; charset=UTF-8">  That's interesting. \
                &nbsp;It leads me to wonder what is the expected
      result from a call to lookupAll in various scenarios. &nbsp;If, after
      the window was showing, the SplitPane divider is pushed all the
      way to one size such that the skin can potentially choose to leave
      the hidden child out of the scene graph, presumable the current
      lookupAll implementation would then fail to find it again.
      <div><br>
      </div>
      <div>I think that either that's a bug, or it needs to be made
        clearer in the documentation that non-rendered child nodes may
        not be found. &nbsp;I personally lean toward "bug", as I think any
        Node reachable through a parent Node's public API to access
        child nodes should be found via Node.lookupAll. &nbsp;I suppose you
        could argue that Scene.lookup is searching the scene graph in a
        more literal sense and wouldn't find some Nodes.</div>
      <div><br>
      </div>
      <div>The docs for Scene.lookup say:</div>
      <div><span class="Apple-tab-span" style="white-space:pre">	</span>"Looks
        for any node within the scene graph based on the specified CSS
        selector."</div>
      <div><span style="caret-color: rgb(71, 71, 71); color: rgb(71, 71,
          71); font-family: &quot;DejaVu Serif&quot;, Georgia,
          &quot;Times New Roman&quot;, Times, serif; font-size: 14px;
          background-color: rgb(255, 255, 255);"><br>
        </span></div>
      <div>The docs for Node.lookup say:</div>
      <div><span class="Apple-tab-span" style="white-space:pre">	</span>"Finds
        this Node, or the first sub-node, based on the given CSS
        selector"</div>
      <div><br>
      </div>
      <div>The docs for Node.lookupAll say:</div>
      <div><span class="Apple-tab-span" style="white-space:pre">	</span>"Finds
        all Nodes, including this one <b>and any children</b>, which
        match the given CSS selector."</div>
      <div><br>
        <div>It doesn't mention the scene graph or if the node is
          currently being rendered in a visible portion of the scene.
          &nbsp;It explicitly states "any children".</div>
        <div><br>
        </div>
        <div>So I'm saying it's a bug.</div>
        <div><br>
        </div>
        <div><br>
        </div>
        <div>Scott</div>
        <div><br>
          <blockquote type="cite">
            <div>On Dec 24, 2022, at 3:34 AM, John Hendrikx
              <a class="moz-txt-link-rfc2396E" \
href="mailto:john.hendrikx@gmail.com">&lt;john.hendrikx@gmail.com&gt;</a> \
wrote:</div>  <br class="Apple-interchange-newline">
            <div>
              <meta http-equiv="Content-Type" content="text/html;
                charset=UTF-8">
              <div>
                <p>Hi,<br>
                </p>
                <p>In this case, this is because SplitPane doesn't
                  actually add its split items as children -- only its
                  Skin does this.&nbsp; Skins are AFAIK installed after a CSS
                  pass.</p>
                <p>In the split pane case, I guess a Skin could choose
                  to completely leave out a child if its splitter
                  completely hides it (ie, dragged all the way to the
                  left or right if allowed).</p>
                <p>This may be another case where it may make sense to
                  have both a document graph (logical graph) and a scene
                  graph as Michael Strauss mentioned here: <a \
class="moz-txt-link-freetext" \
href="https://mail.openjdk.org/pipermail/openjfx-dev/2022-June/034417.html" \
moz-do-not-send="true">https://mail.openjdk.org/pipermail/openjfx-dev/2022-June/034417.html</a></p>
  <p>I doubt this is documented anywhere at all, it's one
                  of those things that doesn't work quite right in
                  JavaFX before a Scene is displayed.<br>
                </p>
                <p>--John<br>
                </p>
                <div class="moz-cite-prefix">On 23/12/2022 23:49, Scott
                  Palmer wrote:<br>
                </div>
                <blockquote type="cite" \
cite="mid:2C7CB4BB-5FC3-4185-9CA3-1202F804E407@gmail.com">  <meta \
http-equiv="content-type" content="text/html;  charset=UTF-8">
                  I just want to make sure this is not expected
                  behaviour. I don't think so, the documentation for
                  lookupAll doesn't mention anything related, but maybe
                  I missed something somewhere else.
                  <div><br>
                    <div>I was just coding something to query the Scene
                      for all SplitPanes and save/restore the divider
                      positions for when my application is exiting and
                      launching and came across this issue.</div>
                    <div>My UI is fully constructed (at least in terms
                      of all the SplitPanes in the scene graph) before
                      it is shown.</div>
                    <div><br>
                    </div>
                    <div>This &nbsp;code:</div>
                    <div><br>
                    </div>
                    <div><span class="Apple-tab-span" \
style="white-space:pre">	</span><font face="Courier \
New">window.getScene().getRoot().lookupAll(".split-pane")</font><br>  <div><br>
                      </div>
                    </div>
                    <div>returns a different number of Nodes if I call
                      it before showing the window versus after showing
                      the window. &nbsp;Specifically, if I call it before
                      showing the window it appears to only return the
                      first SplitPane found in the scene graph, but
                      calling it in an event handler for the window
                      shown event I get all three.</div>
                    <div><br>
                    </div>
                    <div>This can be demonstrated with the following
                      program:</div>
                  </div>
                  <div><br>
                  </div>
                  <div><br>
                  </div>
                  <div>
                    <div><font face="Courier New">import
                        javafx.application.Application;</font></div>
                    <div><font face="Courier New">import
                        javafx.scene.Scene;</font></div>
                    <div><font face="Courier New">import
                        javafx.scene.control.SplitPane;</font></div>
                    <div><font face="Courier New">import
                        javafx.scene.control.TextArea;</font></div>
                    <div><font face="Courier New">import
                        javafx.scene.layout.BorderPane;</font></div>
                    <div><font face="Courier New">import
                        javafx.stage.Stage;</font></div>
                    <div><font face="Courier New">import
                        javafx.stage.Window;</font></div>
                    <div><font face="Courier New"><br>
                      </font></div>
                    <div><font face="Courier New">public class LookupAll
                        extends Application {</font></div>
                    <div><font face="Courier New">&nbsp; &nbsp; Window \
                mainWindow;</font></div>
                    <div><font face="Courier New">&nbsp; &nbsp;&nbsp;</font></div>
                    <div><font face="Courier New">&nbsp; &nbsp; public static void
                        main(String[] args) {</font></div>
                    <div><font face="Courier New">&nbsp; &nbsp; &nbsp; &nbsp; \
                launch(args);</font></div>
                    <div><font face="Courier New">&nbsp; &nbsp; }</font></div>
                    <div><font face="Courier New">&nbsp; &nbsp;&nbsp;</font></div>
                    <div><font face="Courier New">&nbsp; &nbsp; \
                @Override</font></div>
                    <div><font face="Courier New">&nbsp; &nbsp; public void
                        start(Stage primaryStage) throws Exception {</font></div>
                    <div><font face="Courier New">&nbsp; &nbsp; &nbsp; &nbsp; var bp \
= new  BorderPane(new SplitPane(new TextArea(),new
                        SplitPane(new TextArea(),new SplitPane(new
                        TextArea()))));</font></div>
                    <div><font face="Courier New">&nbsp; &nbsp; &nbsp; &nbsp; var \
scene =  new Scene(bp);</font></div>
                    <div><font face="Courier New">&nbsp; &nbsp; &nbsp; &nbsp;
                        primaryStage.setScene(scene);</font></div>
                    <div><font face="Courier New">&nbsp; &nbsp; &nbsp; &nbsp; \
mainWindow =  primaryStage;</font></div>
                    <div><font face="Courier New">&nbsp; &nbsp; &nbsp; &nbsp;
                        System.out.println("Before showing:");</font></div>
                    <div><font face="Courier New">&nbsp; &nbsp; &nbsp; &nbsp;
                        countSplitPanes();</font></div>
                    <div><font face="Courier New">&nbsp; &nbsp; &nbsp; &nbsp;
                        primaryStage.setOnShown(we -&gt; {</font></div>
                    <div><font face="Courier New">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; \
&nbsp;  System.out.println("After showing:");</font></div>
                    <div><font face="Courier New">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; \
&nbsp;  countSplitPanes();</font></div>
                    <div><font face="Courier New">&nbsp; &nbsp; &nbsp; &nbsp; \
                });</font></div>
                    <div><font face="Courier New">&nbsp; &nbsp; &nbsp; &nbsp;
                        primaryStage.show();</font></div>
                    <div><font face="Courier New">&nbsp; &nbsp; }</font></div>
                    <div><font face="Courier New">&nbsp; &nbsp;&nbsp;</font></div>
                    <div><font face="Courier New">&nbsp; &nbsp; private void
                        countSplitPanes() {</font></div>
                    <div><font face="Courier New">&nbsp; &nbsp; &nbsp; &nbsp; var \
splitPanes  =
                        \
                mainWindow.getScene().getRoot().lookupAll(".split-pane");</font></div>
                
                    <div><font face="Courier New">&nbsp; &nbsp; &nbsp; &nbsp;
                        System.out.printf("Found %d SpitPanes:
                        %s\n",splitPanes.size(), splitPanes);</font></div>
                    <div><font face="Courier New">&nbsp; &nbsp; }</font></div>
                    <div><font face="Courier New">}</font></div>
                  </div>
                  <div><br>
                  </div>
                  <div><br>
                  </div>
                  <div><br>
                  </div>
                  <div>
                    <div>Before showing:</div>
                    <div>Found 1 SpitPanes:
                      [SplitPane@16bca2d9[styleClass=split-pane]]</div>
                    <div>After showing:</div>
                    <div>Found 3 SpitPanes:
                      [SplitPane@16bca2d9[styleClass=split-pane],
                      SplitPane@7078ef3c[styleClass=split-pane],
                      SplitPane@56a29626[styleClass=split-pane]]</div>
                  </div>
                  <div><br>
                  </div>
                  <div><br>
                  </div>
                  <div>Regards,</div>
                  <div><br>
                  </div>
                  <div>Scott</div>
                  <div><br>
                  </div>
                </blockquote>
              </div>
            </div>
          </blockquote>
        </div>
        <br>
      </div>
    </blockquote>
  

</div></blockquote></div></body></html>



[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic