<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>