<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  </head>
  <body>
    <p>I saw you resolved the issue already in your next mail.</p>
    <p>As you're modifying the Cell when it is being updated, it won't
      be so easy to do the same thing I'm doing.  For me, the problem
      was that adding additional cells only when they're needed is done
      during `layoutChildren`, which is after CSS has been applied. Any
      new children therefore would temporarily have no CSS applied to
      them.  If those children happen to be in a very visible location
      (like in the center of the screen) you'd see a flash (this can
      happen when a list contains 5 children, but the visible area can
      hold 20; if the list is changed to hold more than the 5 existing
      children, the newly added items would have a brief flash).  By
      moving the code that adds new children to a pulse listener, I can
      add the children before CSS is applied and before `layoutChildren`
      is called.  I suspect this "problem" may be present in more cell
      based skins, but it is not often noticed (white is often a
      standard background color, and the flash is very brief when JavaFX
      runs at 60 fps as it is only there for 1 frame).</p>
    <p>I saw you resolved the problem by calling applyCSS, but there may
      be an alternative; if you could always put a graphic on your cell
      (ie, don't ever set it to `null`) but when you want it hidden just
      change the cell Labeled#contentDisplay to
      ContentDisplay.TEXT_ONLY, you may be able to avoid the graphic
      needing to be added/removed from the node.  Note however that you
      can't share graphics between Nodes, so make sure they all have
      their own instance.  Other ways may also work (setting the graphic
      node to invisible/unmanaged, etc..)</p>
    <p>This may make it possible to avoid having to call applyCSS.<br>
    </p>
    --John<br>
    <br>
    <div class="moz-cite-prefix">On 22/02/2023 01:37, Scott Palmer
      wrote:<br>
    </div>
    <blockquote type="cite"
cite="mid:CAL3e5iFdvEKx2=FtJVoDi-K_P6fTrVbUabpdV+_J5ZUuHe_6jQ@mail.gmail.com">
      <meta http-equiv="content-type" content="text/html; charset=UTF-8">
      <div dir="ltr">
        <div class="gmail_default" style="font-family:arial,sans-serif">I
          agree, this seems like it could be the same issue.  Could you
          give me a little more context as to how this code works? I'm
          not implementing my own skin (maybe I should, I've never tried
          that before).  Is this something I can trigger without a
          custom skin?</div>
        <div class="gmail_default" style="font-family:arial,sans-serif"><br>
        </div>
        <div class="gmail_default" style="font-family:arial,sans-serif">Regards,</div>
        <div class="gmail_default" style="font-family:arial,sans-serif"><br>
        </div>
        <div class="gmail_default" style="font-family:arial,sans-serif">Scott.</div>
      </div>
      <br>
      <div class="gmail_quote">
        <div dir="ltr" class="gmail_attr">On Tue, Feb 21, 2023 at 12:01
          PM 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-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex">
          <div>
            <p>I've run into something similar, maybe even the same
              issue.</p>
            <p>My issue was that modifying the list of cell children (in
              a Skin for ListView) caused a 1 frame white flicker (my
              application is black, so it was annoying) because no CSS
              was applied yet to those newly added children.  This
              occured when the ListView first only had a few children
              and wasn't completely filled, and then switching to a list
              which required more cells to be created. I couldn't find a
              "correct" place to modify the list of children that would
              avoid the flicker (layoutChildren/computePrefWidth are
              places I tried).</p>
            <p>In the end I did this, and added a comment to remind me
              why the hack was there:</p>
            <p>    /*<br>
                   * A pre-layout pulse listener is added to the current
              Scene to manage the<br>
                   * cells before the CSS pass occurs (this could also
              be done with an AnimationTimer).<br>
                   *<br>
                   * If cells are not managed before the CSS pass, new
              cells will be rendered for<br>
                   * one frame without CSS applied. This results in a
              visual artifact (a white flash<br>
                   * for example if the background is supposed to be
              dark, while white is the default<br>
                   * color without any CSS applied).<br>
                   */<br>
                  private final Runnable pulseListener = () -> {<br>
                    int lines = vertical ? visibleColumns.get() :
              visibleRows.get();<br>
                    int firstIndex = (int)(scrollPosition.get()) *
              lines;<br>
                <br>
                    content.manageCells(firstIndex);<br>
                  };</p>
            <p>Now, the reason I think this may be same issue is that
              you're also doing a modification of the children list
              during layout: setting the graphic is sort of equivalent
              to label.getChildren().add(graphic)<br>
            </p>
            <p>--John<br>
            </p>
            <div>On 20/02/2023 20:58, Scott Palmer wrote:<br>
            </div>
            <blockquote type="cite">
              <div dir="ltr">
                <div class="gmail_default"
                  style="font-family:arial,sans-serif">I'm seeing an odd
                  issue with using CSS to colour a Shape when I have it
                  as a child of a TextFlow.</div>
                <div class="gmail_default"
                  style="font-family:arial,sans-serif"><br>
                </div>
                <div class="gmail_default"
                  style="font-family:arial,sans-serif">My use case is a
                  "rich" text Cell in a tree or list.  I want to have
                  the text portion in multiple colours and so instead of
                  using the graphic and text parts of a typical Cell,
                  I'm using only the Graphic and setting it to a
                  TextFlow to get the text colours. This means that I
                  lose the ability to set a graphic independen to the
                  text, and so the graphic is also added to the
                  TextFlow.</div>
                <div class="gmail_default"
                  style="font-family:arial,sans-serif"><br>
                </div>
                <div class="gmail_default"
                  style="font-family:arial,sans-serif">To style the
                  graphics, which are made of simple shapes, I'm using
                  CSS.  It makes it easy to adapt the colours for when a
                  cell is selected etc.  What I've noticed is that as
                  the cell selection moves around the Shape component of
                  the TextFlow flickers, as if it is drawn first using
                  default colours and then the CSS is applied
                  afterward.  I tried working around this by explicitly
                  calling applyCss() on the Shape from the Cell's update
                  method, but it did not help.  If I explicitly set the
                  Stroke and Fill via the Shape API the flickering does
                  not occur.  If I use CSS, but set the Shape as the
                  Cell's graphic and resort to only having plain text,
                  there is no flickering.</div>
                <div class="gmail_default"
                  style="font-family:arial,sans-serif"><br>
                </div>
                <div class="gmail_default"
                  style="font-family:arial,sans-serif">A test program
                  that demonstrates this is below.</div>
                <div class="gmail_default"
                  style="font-family:arial,sans-serif"><br>
                </div>
                <div class="gmail_default"
                  style="font-family:arial,sans-serif">Bug or known
                  limitation?</div>
                <div class="gmail_default"
                  style="font-family:arial,sans-serif"><br>
                </div>
                <div class="gmail_default"
                  style="font-family:arial,sans-serif">Scott</div>
                <div class="gmail_default"
                  style="font-family:arial,sans-serif">------------------------------------</div>
                <div class="gmail_default"
                  style="font-family:arial,sans-serif">package bugs;<br>
                  <br>
                  import javafx.application.Application;<br>
                  import javafx.geometry.Insets;<br>
                  import javafx.scene.Node;<br>
                  import javafx.scene.Scene;<br>
                  import javafx.scene.control.CheckBox;<br>
                  import javafx.scene.control.ContentDisplay;<br>
                  import javafx.scene.control.Label;<br>
                  import javafx.scene.control.ListCell;<br>
                  import javafx.scene.control.ListView;<br>
                  import javafx.scene.control.Tab;<br>
                  import javafx.scene.control.TabPane;<br>
                  import javafx.scene.layout.HBox;<br>
                  import javafx.scene.layout.VBox;<br>
                  import javafx.scene.paint.Color;<br>
                  import javafx.scene.shape.Circle;<br>
                  import javafx.scene.shape.Rectangle;<br>
                  import javafx.scene.shape.Shape;<br>
                  import javafx.scene.text.Text;<br>
                  import javafx.scene.text.TextFlow;<br>
                  import javafx.stage.Stage;<br>
                  <br>
                  <br>
                  public class CSSFlickerInTextFlow extends Application
                  {<br>
                  <br>
                      public static void main(String[] args) {<br>
                          launch(args);<br>
                      }<br>
                  <br>
                      private CheckBox onlyCssCB;<br>
                  <br>
                      @Override<br>
                      public void start(Stage stage) throws Exception {<br>
                          ListView<String> list1 = new
                  ListView<>();<br>
                          ListView<String> list2 = new
                  ListView<>();<br>
                          var items1 = list1.getItems();<br>
                          var items2 = list2.getItems();<br>
                          for (int i = 1; i < 23; i++) {<br>
                              var x = "Item #"+i;<br>
                              items1.add(x);<br>
                              items2.add(x);<br>
                          }<br>
                          list1.setCellFactory(t -> new MyCell1());<br>
                          list2.setCellFactory(t -> new MyCell2());<br>
                  <br>
                          onlyCssCB = new CheckBox("Use only CSS (shapes
                  will flicker in TextFlow)");<br>
                          HBox buttons = new HBox(8, onlyCssCB);<br>
                          buttons.setPadding(new Insets(4));<br>
                  <br>
                          Tab custom = new Tab("Everything in Graphic",
                  list1);<br>
                          Tab withoutColoredText = new Tab("Graphic +
                  Text", list2);<br>
                          TabPane tabs = new TabPane(custom,
                  withoutColoredText);<br>
                  <br>
                          VBox root = new VBox(<br>
                                  new Label("""<br>
                                            Focus in list, cursor up and
                  down, pay attention to the circle.<br>
                                            Try the same with the box
                  checked - circle flickers.<br>
                                            Doesn't happen when not
                  using the TextFlow.<br>
                                            """),<br>
                                  buttons, tabs);<br>
                          root.setPadding(new Insets(4));<br>
                          var scene = new Scene(root);<br>
                          stage.setScene(scene);<br>
                          stage.setTitle("Flickering with CSS in
                  TextFlow");<br>
                          stage.show();<br>
                      }<br>
                  <br>
                      private Shape makeGraphic() {<br>
                          Shape graphic = new Circle(6);<br>
                          if (!onlyCssCB.isSelected()) {<br>
                              graphic.setFill(Color.SALMON); // CSS
                  overrides these but causes flickering if not the same<br>
                              graphic.setStroke(Color.BLACK);<br>
                          }<br>
                          graphic.setStyle("-fx-fill: salmon;
                  -fx-stroke: black;");<br>
                          return graphic;<br>
                      }<br>
                  <br>
                      class MyCell1 extends ListCell<String> {<br>
                  <br>
                          @Override<br>
                          protected void updateItem(String item, boolean
                  empty) {<br>
                              super.updateItem(item, empty);<br>
                             
                  setContentDisplay(ContentDisplay.GRAPHIC_ONLY);<br>
                              setText(null);<br>
                              if (!empty && item != null) {<br>
                                  TextFlow flow = new TextFlow();<br>
                                  Shape graphic = makeGraphic();<br>
                                  graphic.setTranslateY(2);<br>
                                  var nodeList = flow.getChildren();<br>
                                  Text name = new Text(item + " : ");<br>
                                  name.setStyle("-fx-fill:
                  -fx-text-background-color;");<br>
                                  Text extra = new Text("with Color");<br>
                                 
                  extra.setStyle("-fx-fill:ladder(-fx-background, white
                  49%, salmon 50%);");<br>
                                  nodeList.add(graphic);<br>
                                  nodeList.add(new Rectangle(4,0)); //
                  gap<br>
                                  nodeList.add(name);<br>
                                  nodeList.add(extra);<br>
                                  setGraphic(flow);<br>
                              } else {<br>
                                  setGraphic(null);<br>
                              }<br>
                          }<br>
                      }<br>
                  <br>
                      class MyCell2 extends ListCell<String> {<br>
                          @Override<br>
                          protected void updateItem(String item, boolean
                  empty) {<br>
                              super.updateItem(item, empty);<br>
                              if (!empty && item != null) {<br>
                                  setGraphic(makeGraphic());<br>
                                  setText(item);<br>
                              } else {<br>
                                  setText(null);<br>
                                  setGraphic(null);<br>
                              }<br>
                          }<br>
                      }<br>
                  }<br>
                </div>
                <div class="gmail_default"
                  style="font-family:arial,sans-serif"><br>
                </div>
              </div>
            </blockquote>
          </div>
        </blockquote>
      </div>
    </blockquote>
  </body>
</html>