<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  </head>
  <body>
    <p>I said I'd do it tomorrow, but here is a full example anyway with
      pre-loaded images, and without external dependencies:</p>
    <p><br>
    </p>
    <p>package org.int4.sdui.ui;<br>
      <br>
      import javafx.application.Application;<br>
      import javafx.scene.Scene;<br>
      import javafx.scene.control.Button;<br>
      import javafx.scene.control.ListCell;<br>
      import javafx.scene.control.ListView;<br>
      import javafx.scene.control.TextArea;<br>
      import javafx.scene.image.Image;<br>
      import javafx.scene.image.ImageView;<br>
      import javafx.scene.layout.HBox;<br>
      import javafx.scene.layout.Priority;<br>
      import javafx.scene.layout.VBox;<br>
      import javafx.stage.Stage;<br>
      <br>
      public class Main2 {<br>
      <br>
        public static void main(String[] args) {<br>
          Application.launch(UI.class, args);<br>
        }<br>
      <br>
        public static class UI extends Application {<br>
      <br>
          @Override<br>
          public void start(Stage primaryStage) throws
      InterruptedException {<br>
            Image image1 = new Image(<a class="moz-txt-link-rfc2396E" href="https://picsum.photos/512/512">"https://picsum.photos/512/512"</a>);<br>
            Image image2 = new Image(<a class="moz-txt-link-rfc2396E" href="https://picsum.photos/512/512">"https://picsum.photos/512/512"</a>);<br>
      <br>
            TextArea prompt = new TextArea("a flower on Mars");<br>
            Button button = new Button("Submit");<br>
            ListView<Image> listView = new ListView<>();<br>
      <br>
            while(image1.isBackgroundLoading() ||
      image2.isBackgroundLoading()) {<br>
              Thread.sleep(100);<br>
            }<br>
      <br>
            listView.getItems().addAll(image1, image2);<br>
            listView.setCellFactory(lv -> {<br>
              final ImageView imageView = new ImageView();<br>
      <br>
              return new ListCell<>() {<br>
                protected void updateItem(Image image, boolean empty) {<br>
                  if(empty) {<br>
                    setGraphic(null);<br>
                  }<br>
                  else {<br>
                    imageView.setImage(image);<br>
                    setGraphic(imageView);<br>
                  }<br>
                }<br>
              };<br>
            });<br>
      <br>
            HBox hbox = new HBox() {{<br>
              getChildren().addAll(<br>
                new VBox() {{<br>
                  getChildren().addAll(prompt, button);<br>
                }},<br>
                listView<br>
              );<br>
            }};<br>
      <br>
            HBox.setHgrow(listView, Priority.ALWAYS);<br>
      <br>
            Scene scene = new Scene(hbox);<br>
      <br>
            primaryStage.setScene(scene);<br>
            primaryStage.show();<br>
          }<br>
        }<br>
      }<br>
      <br>
      <br>
      <br>
      <br>
      <br>
      --John<br>
    </p>
    <div class="moz-cite-prefix">On 12/07/2023 01:17, Andy Goryachev
      wrote:<br>
    </div>
    <blockquote type="cite"
cite="mid:DM5PR1001MB21729F042AF190CD54269545E531A@DM5PR1001MB2172.namprd10.prod.outlook.com">
      <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
      <meta name="Generator" content="Microsoft Word 15 (filtered
        medium)">
      <style>@font-face
        {font-family:"Cambria Math";
        panose-1:2 4 5 3 5 4 6 3 2 4;}@font-face
        {font-family:Calibri;
        panose-1:2 15 5 2 2 2 4 3 2 4;}@font-face
        {font-family:"Iosevka Fixed SS16";
        panose-1:2 0 5 9 3 0 0 0 0 4;}@font-face
        {font-family:"Times New Roman \(Body CS\)";
        panose-1:2 11 6 4 2 2 2 2 2 4;}p.MsoNormal, li.MsoNormal, div.MsoNormal
        {margin:0in;
        font-size:10.0pt;
        font-family:"Calibri",sans-serif;}a:link, span.MsoHyperlink
        {mso-style-priority:99;
        color:blue;
        text-decoration:underline;}span.EmailStyle19
        {mso-style-type:personal-reply;
        font-family:"Iosevka Fixed SS16";
        color:windowtext;}.MsoChpDefault
        {mso-style-type:export-only;
        font-size:10.0pt;
        mso-ligatures:none;}div.WordSection1
        {page:WordSection1;}</style>
      <div class="WordSection1">
        <p class="MsoNormal"><span
            style="font-size:11.0pt;font-family:"Iosevka Fixed
            SS16"">I'll need to replicate this scenario to be able
            to say anything definitive.<o:p></o:p></span></p>
        <p class="MsoNormal"><span
            style="font-size:11.0pt;font-family:"Iosevka Fixed
            SS16""><o:p> </o:p></span></p>
        <p class="MsoNormal"><span
            style="font-size:11.0pt;font-family:"Iosevka Fixed
            SS16"">Just by looking at the cell factory code though,
            I suspect there might be some async processing around
            <o:p></o:p></span></p>
        <p class="MsoNormal"><span
            style="font-size:11.0pt;font-family:"Iosevka Fixed
            SS16""><o:p> </o:p></span></p>
        <p class="MsoNormal"><span style="font-size:11.0pt">new
            ImageView(new Image(new <br>
            > ByteArrayInputStream(imageHandle.getImageData()))));</span><span
            style="font-size:11.0pt;font-family:"Iosevka Fixed
            SS16"">
          </span><span style="font-size:11.0pt"><o:p></o:p></span></p>
        <p class="MsoNormal"><span
            style="font-size:11.0pt;font-family:"Iosevka Fixed
            SS16""><o:p> </o:p></span></p>
        <p class="MsoNormal"><span
            style="font-size:11.0pt;font-family:"Iosevka Fixed
            SS16"">which might cause the issue.<o:p></o:p></span></p>
        <p class="MsoNormal"><span
            style="font-size:11.0pt;font-family:"Iosevka Fixed
            SS16""><o:p> </o:p></span></p>
        <p class="MsoNormal"><span
            style="font-size:11.0pt;font-family:"Iosevka Fixed
            SS16"">Could you try pre-loading images?<o:p></o:p></span></p>
        <p class="MsoNormal"><span
            style="font-size:11.0pt;font-family:"Iosevka Fixed
            SS16""><o:p> </o:p></span></p>
        <p class="MsoNormal"><span
            style="font-size:11.0pt;font-family:"Iosevka Fixed
            SS16"">-andy<o:p></o:p></span></p>
        <p class="MsoNormal"><span
            style="font-size:11.0pt;font-family:"Iosevka Fixed
            SS16""><o:p> </o:p></span></p>
        <p class="MsoNormal"><span
            style="font-size:11.0pt;font-family:"Iosevka Fixed
            SS16""><o:p> </o:p></span></p>
        <p class="MsoNormal"><span
            style="font-size:11.0pt;font-family:"Iosevka Fixed
            SS16""><o:p> </o:p></span></p>
        <div id="mail-editor-reference-message-container">
          <div>
            <div style="border:none;border-top:solid #B5C4DF
              1.0pt;padding:3.0pt 0in 0in 0in">
              <p class="MsoNormal" style="margin-bottom:12.0pt"><b><span
                    style="font-size:12.0pt;color:black">From:
                  </span></b><span style="font-size:12.0pt;color:black">openjfx-dev
                  <a class="moz-txt-link-rfc2396E" href="mailto:openjfx-dev-retn@openjdk.org"><openjfx-dev-retn@openjdk.org></a> on behalf of
                  Kevin Rushforth <a class="moz-txt-link-rfc2396E" href="mailto:kevin.rushforth@oracle.com"><kevin.rushforth@oracle.com></a><br>
                  <b>Date: </b>Tuesday, July 11, 2023 at 15:58<br>
                  <b>To: </b><a class="moz-txt-link-abbreviated" href="mailto:openjfx-dev@openjdk.org">openjfx-dev@openjdk.org</a>
                  <a class="moz-txt-link-rfc2396E" href="mailto:openjfx-dev@openjdk.org"><openjfx-dev@openjdk.org></a><br>
                  <b>Subject: </b>Re: ListView with ImageViews for
                  cells very bugged?<o:p></o:p></span></p>
            </div>
            <div>
              <p class="MsoNormal" style="margin-bottom:12.0pt"><span
                  style="font-size:11.0pt">What you have should work,
                  but will create redundant images and
                  <br>
                  ImageView ojbects. The recommendation is to create the
                  nodes (ImageView <br>
                  in this case) in the constructor of the cell factory
                  and call setGraphic <br>
                  with either null or that factory's node.<br>
                  <br>
                  Having said that, I doubt that this is related to the
                  visual problems <br>
                  you are seeing. Maybe Ajit or Andy have some ideas.<br>
                  <br>
                  -- Kevin<br>
                  <br>
                  <br>
                  On 7/11/2023 3:50 PM, John Hendrikx wrote:<br>
                  > I tend to avoid ListView, because for some reason
                  it seems to just <br>
                  > never do what I want unless used for its mundane
                  rows of text use <br>
                  > case. I so far always just implemented my own
                  skin for ListView that <br>
                  > deals with displays that have many images that
                  need to scroll <br>
                  > smoothly, but...<br>
                  ><br>
                  > Recently, I've again attempted to use ListView,
                  this time for showing <br>
                  > (so far) fixed size ImageViews with images
                  exactly 512x512 pixels in <br>
                  > size:<br>
                  ><br>
                  > The cell factory looks like this, which I think
                  is a correct <br>
                  > implementation:<br>
                  ><br>
                  >       listView.setCellFactory(lv -> {<br>
                  >         return new ListCell<>() {<br>
                  >           protected void updateItem(ImageHandle
                  imageHandle, boolean <br>
                  > empty) {<br>
                  >             if(empty) {<br>
                  >               setGraphic(null);<br>
                  >             }<br>
                  >             else {<br>
                  >               try {<br>
                  >                 setGraphic(new ImageView(new
                  Image(new <br>
                  >
                  ByteArrayInputStream(imageHandle.getImageData()))));<br>
                  >               }<br>
                  >               catch(IOException e) {<br>
                  >                 e.printStackTrace();<br>
                  >               }<br>
                  >             }<br>
                  >           }<br>
                  >         };<br>
                  >       });<br>
                  ><br>
                  > Now, this is with JavaFX 21-ea-24 (but also
                  happens on 19).  I spotted <br>
                  > the following IMHO bugs:<br>
                  ><br>
                  > 1) When the ImageView is so large that a single
                  row is only partially <br>
                  > visible, the scrollbar is incorrect (it shows a
                  full bar, even if half <br>
                  > of a row is displayed).<br>
                  ><br>
                  > 2) The vertical scrollbar doesn't respond to a
                  click in the non-thumb <br>
                  > area at all (you'd expect to make it scroll a
                  page up or down that way)<br>
                  ><br>
                  > 3) When jerkily resizing the window, I can
                  sometimes have a vertical + <br>
                  > horizontal scrollbar when there's a full row
                  visible + anywhere from 0 <br>
                  > to 10 extra empty pixels (probably the potential
                  height of a <br>
                  > horizontal scrollbar) with the vertical scroll
                  bar still visible.  The <br>
                  > algorithm to hide the scrollbar apparently is not
                  deterministic and <br>
                  > depends on mouse movement speed.<br>
                  ><br>
                  > 4) When a row is less than half visible,
                  scrolling the window down to <br>
                  > another ImageView will jump the view and hide the
                  first cell that <br>
                  > should still be visible for the bottom 0-49% of
                  its height.<br>
                  ><br>
                  > 5) It's possible to get the vertical scroll bar
                  in such a state that <br>
                  > it doesn't respond to the mouse any more at all,
                  even by dragging the <br>
                  > thumb.  Some keyboard action and mouse scrolling
                  sometimes restores it <br>
                  > to relatively normal functioning.<br>
                  ><br>
                  > 6) Mouse wheel scrolling acts weird.  With one
                  large cell visible and <br>
                  > two rows available, scrolling only **down** on
                  the mouse wheel will <br>
                  > scroll down, then jump back up, and scroll down
                  again... it's <br>
                  > impossible to scroll all the way down to get to a
                  point where it stops <br>
                  > scrolling as it keeps jumping back.<br>
                  ><br>
                  > This is with ImageView's.  I suppose they're
                  known to have problems... <br>
                  > but then I switched to a Region, which contain an
                  ImageView with <br>
                  > proper min/pref/max implementations.  This
                  improved the situation <br>
                  > somewhat.  The scrollbar was much more reliable,
                  but I still saw <br>
                  > almost all of the above issues, but somewhat more
                  reliable than <br>
                  > before.  Still rows would disappear when (for the
                  most part) <br>
                  > invisible, those and the jumps of the view are
                  just totally unacceptable.<br>
                  ><br>
                  > I'm not quite sure what to make of this, it seems
                  the control is not <br>
                  > meant for arbitrary graphics.<br>
                  ><br>
                  > --John<br>
                  ><br>
                  ><br>
                  ><br>
                  > package org.int4.sdui.ui;<br>
                  ><br>
                  > import hs.mediasystem.util.image.ImageHandle;<br>
                  > import
                  hs.mediasystem.util.javafx.control.Containers;<br>
                  ><br>
                  > import java.io.ByteArrayInputStream;<br>
                  > import java.io.IOException;<br>
                  > import java.util.Base64;<br>
                  > import java.util.List;<br>
                  ><br>
                  > import javafx.application.Application;<br>
                  > import javafx.scene.Scene;<br>
                  > import javafx.scene.control.Button;<br>
                  > import javafx.scene.control.ListCell;<br>
                  > import javafx.scene.control.ListView;<br>
                  > import javafx.scene.control.TextArea;<br>
                  > import javafx.scene.image.Image;<br>
                  > import javafx.scene.image.ImageView;<br>
                  > import javafx.scene.layout.HBox;<br>
                  > import javafx.scene.layout.Priority;<br>
                  > import javafx.stage.Stage;<br>
                  ><br>
                  > import kong.unirest.core.Unirest;<br>
                  ><br>
                  > public class Main {<br>
                  ><br>
                  >   public static void main(String[] args) {<br>
                  >     Application.launch(UI.class, args);<br>
                  >   }<br>
                  ><br>
                  >   public static class UI extends Application {<br>
                  ><br>
                  >     @Override<br>
                  >     public void start(Stage primaryStage) {<br>
                  >       TextArea prompt = new TextArea("a flower on
                  Mars");<br>
                  >       Button button = new Button("Submit");<br>
                  >       ListView<ImageHandle> listView = new
                  ListView<>();<br>
                  ><br>
                  >       listView.setCellFactory(lv -> {<br>
                  >         return new ListCell<>() {<br>
                  >           protected void updateItem(ImageHandle
                  imageHandle, boolean <br>
                  > empty) {<br>
                  >             if(empty) {<br>
                  >               setGraphic(null);<br>
                  >             }<br>
                  >             else {<br>
                  >               try {<br>
                  >                 setGraphic(new ImageView(new
                  Image(new <br>
                  >
                  ByteArrayInputStream(imageHandle.getImageData()))));<br>
                  >               }<br>
                  >               catch(IOException e) {<br>
                  >                 e.printStackTrace();<br>
                  >               }<br>
                  >             }<br>
                  >           }<br>
                  >         };<br>
                  >       });<br>
                  ><br>
                  >       button.setOnAction(e -> {<br>
                  >         Txt2ImgResponse response =
                  textToImage(prompt.getText());<br>
                  ><br>
                  >         for(String image : response.images) {<br>
                  >           listView.getItems().add(new <br>
                  >
                  InMemoryImageHandle(Base64.getDecoder().decode(image)));<br>
                  >         }<br>
                  >       });<br>
                  ><br>
                  >       HBox hbox =
                  Containers.hbox(Containers.vbox(prompt, button), <br>
                  > listView);<br>
                  ><br>
                  >       HBox.setHgrow(listView, Priority.ALWAYS);<br>
                  ><br>
                  >       Scene scene = new Scene(hbox);<br>
                  ><br>
                  >       primaryStage.setScene(scene);<br>
                  >       primaryStage.show();<br>
                  >     }<br>
                  ><br>
                  >     private Txt2ImgResponse textToImage(String
                  prompt) {<br>
                  >       return Unirest.post("<a
                    href="http://127.0.0.1:7860/sdapi/v1/txt2img"
                    moz-do-not-send="true" class="moz-txt-link-freetext">http://127.0.0.1:7860/sdapi/v1/txt2img</a>")<br>
                  >         .body(new Txt2Img(prompt, 5))<br>
                  >         .contentType("application/json")<br>
                  >         .asObject(Txt2ImgResponse.class)<br>
                  >         .getBody();<br>
                  >     }<br>
                  >   }<br>
                  ><br>
                  >   static class InMemoryImageHandle implements
                  ImageHandle {<br>
                  >     private final byte[] data;<br>
                  ><br>
                  >     public InMemoryImageHandle(byte[] data) {<br>
                  >       this.data = data;<br>
                  >     }<br>
                  ><br>
                  >     @Override<br>
                  >     public byte[] getImageData() {<br>
                  >       return data;<br>
                  >     }<br>
                  ><br>
                  >     @Override<br>
                  >     public String getKey() {<br>
                  >       return null;<br>
                  >     }<br>
                  ><br>
                  >     @Override<br>
                  >     public boolean isFastSource() {<br>
                  >       return true;<br>
                  >     }<br>
                  >   }<br>
                  ><br>
                  >   record Txt2Img(String prompt, int steps) {}<br>
                  >   record Txt2ImgResponse(List<String>
                  images) {}<br>
                  > }<br>
                  ><br>
                  ><br>
                  ><o:p></o:p></span></p>
            </div>
          </div>
        </div>
      </div>
    </blockquote>
  </body>
</html>