ListView with ImageViews for cells very bugged?

John Hendrikx john.hendrikx at gmail.com
Wed Jul 12 16:26:56 UTC 2023


Yes, sorry, it does mention that, and I missed it by mistake, late night 
programming I guess.

--John

On 12/07/2023 16:57, Kevin Rushforth wrote:
> The updateItem docs [1] already say this. I had missed that the test 
> program didn't do this, so thanks to Ajit for pointing it out.
>
> And yes, https://bugs.openjdk.org/browse/JDK-8090254 should be closed 
> as not an issue with a reference to the doc bug that clarified this.
>
> -- Kevin
>
> [1] 
> https://download.java.net/java/early_access/javafx21/docs/api/javafx.controls/javafx/scene/control/Cell.html#updateItem(T,boolean)
>
> On 7/12/2023 7:50 AM, Andy Goryachev wrote:
>>
>> Ajit is right - perhaps javadoc for updateItem() should explicitly 
>> mention this?
>>
>> Also, perhaps https://bugs.openjdk.org/browse/JDK-8090254 should be 
>> closed - we recently updated javadoc to read
>>
>>
>>       Warning: Nodes should not be inserted directly into the items list
>>
>> (this is a different issue altogether)
>>
>> -andy
>>
>> *From: *Ajit Ghaisas <ajit.ghaisas at oracle.com>
>> *Date: *Wednesday, July 12, 2023 at 02:26
>> *To: *John Hendrikx <john.hendrikx at gmail.com>
>> *Cc: *openjfx-dev at openjdk.org <openjfx-dev at openjdk.org>, Andy 
>> Goryachev <andy.goryachev at oracle.com>
>> *Subject: *Re: ListView with ImageViews for cells very bugged?
>>
>> Hi John,
>>
>>  This looks like a user code issue and not a JavaFX bug.
>>
>>  Most of the vertical scrollbar issues that you have mentioned get 
>> fixed by adding a call to "super.updateItem(image, empty);" as a 
>> first call in the cell factory method "protected void 
>> updateItem(Image image, boolean empty)”
>>
>> I am seeing an exception when I scroll fully down and then scroll up 
>> by clicking empty area on the vertical scrollbar. This looks like a 
>> separate issue though.
>>
>> Regards,
>>
>> Ajit
>>
>>
>>
>>     On 12-Jul-2023, at 5:18 AM, Andy Goryachev
>>     <andy.goryachev at oracle.com> wrote:
>>
>>     Thank you for the code sample, John!
>>
>>     Had to replace loading from https:// to a local file://, but I do
>>     see some of the issues you've mentioned (on macOS):
>>
>>     2), 5), and 6).
>>
>>     There is also a new issue:
>>
>>     7) when the top of the cell is outside of the view area, the
>>     image is not shown at all (but the cell is sized correctly).
>>
>>     All this is indeed weird. Looks like the time is right to create
>>     a bug, unless it's this one:
>>
>>     JDK-8090254 <https://bugs.openjdk.org/browse/JDK-8090254>
>>
>>     	
>>
>>     [ListView] page up/down navigation doesn't work, when items are
>>     large (again!) <https://bugs.openjdk.org/browse/JDK-8090254>
>>
>>     -andy
>>
>>     *From:*openjfx-dev <openjfx-dev-retn at openjdk.org> on behalf of
>>     John Hendrikx <john.hendrikx at gmail.com>
>>     *Date:*Tuesday, July 11, 2023 at 16:34
>>     *To:*openjfx-dev at openjdk.org <openjfx-dev at openjdk.org>
>>     *Subject:*Re: ListView with ImageViews for cells very bugged?
>>
>>     I said I'd do it tomorrow, but here is a full example anyway with
>>     pre-loaded images, and without external dependencies:
>>
>>     package org.int4.sdui.ui;
>>
>>     import javafx.application.Application;
>>     import javafx.scene.Scene;
>>     import javafx.scene.control.Button;
>>     import javafx.scene.control.ListCell;
>>     import javafx.scene.control.ListView;
>>     import javafx.scene.control.TextArea;
>>     import javafx.scene.image.Image;
>>     import javafx.scene.image.ImageView;
>>     import javafx.scene.layout.HBox;
>>     import javafx.scene.layout.Priority;
>>     import javafx.scene.layout.VBox;
>>     import javafx.stage.Stage;
>>
>>     public class Main2 {
>>
>>       public static void main(String[] args) {
>>         Application.launch(UI.class, args);
>>       }
>>
>>       public static class UI extends Application {
>>
>>         @Override
>>         public void start(Stage primaryStage) throws
>>     InterruptedException {
>>           Image image1 = new Image("https://picsum.photos/512/512"
>>     <https://picsum.photos/512/512>);
>>           Image image2 = new Image("https://picsum.photos/512/512"
>>     <https://picsum.photos/512/512>);
>>
>>           TextArea prompt = new TextArea("a flower on Mars");
>>           Button button = new Button("Submit");
>>           ListView<Image> listView = new ListView<>();
>>
>>           while(image1.isBackgroundLoading() ||
>>     image2.isBackgroundLoading()) {
>>             Thread.sleep(100);
>>           }
>>
>>           listView.getItems().addAll(image1, image2);
>>           listView.setCellFactory(lv -> {
>>             final ImageView imageView = new ImageView();
>>
>>             return new ListCell<>() {
>>               protected void updateItem(Image image, boolean empty) {
>>                 if(empty) {
>>                   setGraphic(null);
>>                 }
>>                 else {
>>                   imageView.setImage(image);
>>                   setGraphic(imageView);
>>                 }
>>               }
>>             };
>>           });
>>
>>           HBox hbox = new HBox() {{
>>             getChildren().addAll(
>>               new VBox() {{
>>                 getChildren().addAll(prompt, button);
>>               }},
>>               listView
>>             );
>>           }};
>>
>>           HBox.setHgrow(listView, Priority.ALWAYS);
>>
>>           Scene scene = new Scene(hbox);
>>
>>           primaryStage.setScene(scene);
>>           primaryStage.show();
>>         }
>>       }
>>     }
>>
>>
>>
>>
>>
>>     --John
>>
>>     On 12/07/2023 01:17, Andy Goryachev wrote:
>>
>>         I'll need to replicate this scenario to be able to say
>>         anything definitive.
>>
>>         Just by looking at the cell factory code though, I suspect
>>         there might be some async processing around
>>
>>         new ImageView(new Image(new
>>         > ByteArrayInputStream(imageHandle.getImageData()))));
>>
>>         which might cause the issue.
>>
>>         Could you try pre-loading images?
>>
>>         -andy
>>
>>         *From:*openjfx-dev<openjfx-dev-retn at openjdk.org>
>>         <mailto:openjfx-dev-retn at openjdk.org>on behalf of Kevin
>>         Rushforth<kevin.rushforth at oracle.com>
>>         <mailto:kevin.rushforth at oracle.com>
>>         *Date:*Tuesday, July 11, 2023 at 15:58
>>         *To:*openjfx-dev at openjdk.org<openjfx-dev at openjdk.org>
>>         <mailto:openjfx-dev at openjdk.org>
>>         *Subject:*Re: ListView with ImageViews for cells very bugged?
>>
>>         What you have should work, but will create redundant images and
>>         ImageView ojbects. The recommendation is to create the nodes
>>         (ImageView
>>         in this case) in the constructor of the cell factory and call
>>         setGraphic
>>         with either null or that factory's node.
>>
>>         Having said that, I doubt that this is related to the visual
>>         problems
>>         you are seeing. Maybe Ajit or Andy have some ideas.
>>
>>         -- Kevin
>>
>>
>>         On 7/11/2023 3:50 PM, John Hendrikx wrote:
>>         > I tend to avoid ListView, because for some reason it seems
>>         to just
>>         > never do what I want unless used for its mundane rows of
>>         text use
>>         > case. I so far always just implemented my own skin for
>>         ListView that
>>         > deals with displays that have many images that need to scroll
>>         > smoothly, but...
>>         >
>>         > Recently, I've again attempted to use ListView, this time
>>         for showing
>>         > (so far) fixed size ImageViews with images exactly 512x512
>>         pixels in
>>         > size:
>>         >
>>         > The cell factory looks like this, which I think is a correct
>>         > implementation:
>>         >
>>         > listView.setCellFactory(lv -> {
>>         >         return new ListCell<>() {
>>         >           protected void updateItem(ImageHandle
>>         imageHandle, boolean
>>         > empty) {
>>         >             if(empty) {
>>         > setGraphic(null);
>>         >             }
>>         >             else {
>>         >               try {
>>         > setGraphic(new ImageView(new Image(new
>>         > ByteArrayInputStream(imageHandle.getImageData()))));
>>         >               }
>>         > catch(IOException e) {
>>         > e.printStackTrace();
>>         >               }
>>         >             }
>>         >           }
>>         >         };
>>         >       });
>>         >
>>         > Now, this is with JavaFX 21-ea-24 (but also happens on
>>         19).  I spotted
>>         > the following IMHO bugs:
>>         >
>>         > 1) When the ImageView is so large that a single row is only
>>         partially
>>         > visible, the scrollbar is incorrect (it shows a full bar,
>>         even if half
>>         > of a row is displayed).
>>         >
>>         > 2) The vertical scrollbar doesn't respond to a click in the
>>         non-thumb
>>         > area at all (you'd expect to make it scroll a page up or
>>         down that way)
>>         >
>>         > 3) When jerkily resizing the window, I can sometimes have a
>>         vertical +
>>         > horizontal scrollbar when there's a full row visible +
>>         anywhere from 0
>>         > to 10 extra empty pixels (probably the potential height of a
>>         > horizontal scrollbar) with the vertical scroll bar still
>>         visible.  The
>>         > algorithm to hide the scrollbar apparently is not
>>         deterministic and
>>         > depends on mouse movement speed.
>>         >
>>         > 4) When a row is less than half visible, scrolling the
>>         window down to
>>         > another ImageView will jump the view and hide the first
>>         cell that
>>         > should still be visible for the bottom 0-49% of its height.
>>         >
>>         > 5) It's possible to get the vertical scroll bar in such a
>>         state that
>>         > it doesn't respond to the mouse any more at all, even by
>>         dragging the
>>         > thumb.  Some keyboard action and mouse scrolling sometimes
>>         restores it
>>         > to relatively normal functioning.
>>         >
>>         > 6) Mouse wheel scrolling acts weird.  With one large cell
>>         visible and
>>         > two rows available, scrolling only **down** on the mouse
>>         wheel will
>>         > scroll down, then jump back up, and scroll down again... it's
>>         > impossible to scroll all the way down to get to a point
>>         where it stops
>>         > scrolling as it keeps jumping back.
>>         >
>>         > This is with ImageView's.  I suppose they're known to have
>>         problems...
>>         > but then I switched to a Region, which contain an ImageView
>>         with
>>         > proper min/pref/max implementations.  This improved the
>>         situation
>>         > somewhat.  The scrollbar was much more reliable, but I
>>         still saw
>>         > almost all of the above issues, but somewhat more reliable than
>>         > before.  Still rows would disappear when (for the most part)
>>         > invisible, those and the jumps of the view are just totally
>>         unacceptable.
>>         >
>>         > I'm not quite sure what to make of this, it seems the
>>         control is not
>>         > meant for arbitrary graphics.
>>         >
>>         > --John
>>         >
>>         >
>>         >
>>         > package org.int4.sdui.ui;
>>         >
>>         > import hs.mediasystem.util.image.ImageHandle;
>>         > import hs.mediasystem.util.javafx.control.Containers;
>>         >
>>         > import java.io.ByteArrayInputStream;
>>         > import java.io.IOException;
>>         > import java.util.Base64;
>>         > import java.util.List;
>>         >
>>         > import javafx.application.Application;
>>         > import javafx.scene.Scene;
>>         > import javafx.scene.control.Button;
>>         > import javafx.scene.control.ListCell;
>>         > import javafx.scene.control.ListView;
>>         > import javafx.scene.control.TextArea;
>>         > import javafx.scene.image.Image;
>>         > import javafx.scene.image.ImageView;
>>         > import javafx.scene.layout.HBox;
>>         > import javafx.scene.layout.Priority;
>>         > import javafx.stage.Stage;
>>         >
>>         > import kong.unirest.core.Unirest;
>>         >
>>         > public class Main {
>>         >
>>         >   public static void main(String[] args) {
>>         > Application.launch(UI.class, args);
>>         >   }
>>         >
>>         >   public static class UI extends Application {
>>         >
>>         >     @Override
>>         >     public void start(Stage primaryStage) {
>>         >       TextArea prompt = new TextArea("a flower on Mars");
>>         >       Button button = new Button("Submit");
>>         > ListView<ImageHandle> listView = new ListView<>();
>>         >
>>         > listView.setCellFactory(lv -> {
>>         >         return new ListCell<>() {
>>         >           protected void updateItem(ImageHandle
>>         imageHandle, boolean
>>         > empty) {
>>         >             if(empty) {
>>         > setGraphic(null);
>>         >             }
>>         >             else {
>>         >               try {
>>         > setGraphic(new ImageView(new Image(new
>>         > ByteArrayInputStream(imageHandle.getImageData()))));
>>         >               }
>>         > catch(IOException e) {
>>         > e.printStackTrace();
>>         >               }
>>         >             }
>>         >           }
>>         >         };
>>         >       });
>>         >
>>         >       button.setOnAction(e -> {
>>         >         Txt2ImgResponse response =
>>         textToImage(prompt.getText());
>>         >
>>         >         for(String image : response.images) {
>>         > listView.getItems().add(new
>>         > InMemoryImageHandle(Base64.getDecoder().decode(image)));
>>         >         }
>>         >       });
>>         >
>>         >       HBox hbox = Containers.hbox(Containers.vbox(prompt,
>>         button),
>>         > listView);
>>         >
>>         >       HBox.setHgrow(listView, Priority.ALWAYS);
>>         >
>>         >       Scene scene = new Scene(hbox);
>>         >
>>         > primaryStage.setScene(scene);
>>         >       primaryStage.show();
>>         >     }
>>         >
>>         >     private Txt2ImgResponse textToImage(String prompt) {
>>         >       return
>>         Unirest.post("http://127.0.0.1:7860/sdapi/v1/txt2img")
>>         >         .body(new Txt2Img(prompt, 5))
>>         > .contentType("application/json")
>>         > .asObject(Txt2ImgResponse.class)
>>         >         .getBody();
>>         >     }
>>         >   }
>>         >
>>         >   static class InMemoryImageHandle implements ImageHandle {
>>         >     private final byte[] data;
>>         >
>>         >     public InMemoryImageHandle(byte[] data) {
>>         >       this.data = data;
>>         >     }
>>         >
>>         >     @Override
>>         >     public byte[] getImageData() {
>>         >       return data;
>>         >     }
>>         >
>>         >     @Override
>>         >     public String getKey() {
>>         >       return null;
>>         >     }
>>         >
>>         >     @Override
>>         >     public boolean isFastSource() {
>>         >       return true;
>>         >     }
>>         >   }
>>         >
>>         >   record Txt2Img(String prompt, int steps) {}
>>         >   record Txt2ImgResponse(List<String> images) {}
>>         > }
>>         >
>>         >
>>         >
>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/openjfx-dev/attachments/20230712/3a6c4451/attachment-0001.htm>


More information about the openjfx-dev mailing list