ListView with ImageViews for cells very bugged?

Andy Goryachev andy.goryachev at oracle.com
Wed Jul 12 15:13:46 UTC 2023


resending with a smaller screenshot -


From: Andy Goryachev <andy.goryachev at oracle.com>
Date: Wednesday, July 12, 2023 at 08:02
To: Kevin Rushforth <kevin.rushforth at oracle.com>, Ajit Ghaisas <ajit.ghaisas at oracle.com>, John Hendrikx <john.hendrikx at gmail.com>
Cc: openjfx-dev at openjdk.org <openjfx-dev at openjdk.org>
Subject: Re: ListView with ImageViews for cells very bugged?
I think we just found a bug in Eclipse: it shows javadoc for the wrong method -

[cid:image002.png at 01D9B498.B88B8400]



:-(

-andy




From: Kevin Rushforth <kevin.rushforth at oracle.com>
Date: Wednesday, July 12, 2023 at 07:57
To: Andy Goryachev <andy.goryachev at oracle.com>, Ajit Ghaisas <ajit.ghaisas at oracle.com>, John Hendrikx <john.hendrikx at gmail.com>
Cc: openjfx-dev at openjdk.org <openjfx-dev at openjdk.org>
Subject: Re: ListView with ImageViews for cells very bugged?
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><mailto:ajit.ghaisas at oracle.com>
Date: Wednesday, July 12, 2023 at 02:26
To: John Hendrikx <john.hendrikx at gmail.com><mailto:john.hendrikx at gmail.com>
Cc: openjfx-dev at openjdk.org<mailto:openjfx-dev at openjdk.org> <openjfx-dev at openjdk.org><mailto:openjfx-dev at openjdk.org>, Andy Goryachev <andy.goryachev at oracle.com><mailto: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><mailto:andy.goryachev at oracle.com> wrote:

Thank you for the code sample, John!

Had to replace loading from https:// to a local file://<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><mailto:openjfx-dev-retn at openjdk.org> on behalf of John Hendrikx <john.hendrikx at gmail.com><mailto:john.hendrikx at gmail.com>
Date: Tuesday, July 11, 2023 at 16:34
To: openjfx-dev at openjdk.org<mailto: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?

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<mailto: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/3918e30a/attachment-0001.htm>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: image002.png
Type: image/png
Size: 127888 bytes
Desc: image002.png
URL: <https://mail.openjdk.org/pipermail/openjfx-dev/attachments/20230712/3918e30a/image002-0001.png>


More information about the openjfx-dev mailing list