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