6

I've been searching some threads about JavaFx ListView still it's hard to look for a simple yet easy solution for putting a JavaFx ImageView inside JavaFx ListView. I am trying to create a chat application using JavaFx framework. at the photo it should look like that.This is not duplicate because the other thread is vague for a beginner like me. ListView with imageview inside

I tried something like this. I'm totally noob to this thanks in advance!

import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.Scene;
import javafx.scene.control.ListCell;
import javafx.scene.control.ListView;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.Priority;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

public class Main extends Application {
     ImageView imageView = new ImageView();
     Image image = new Image(Main.class.getResourceAsStream("bell.jpg"));
    ListView<String> list = new ListView<String>();
    ObservableList<String> data = FXCollections.observableArrayList(
            "chocolate", "salmon", "gold", "coral", "darkorchid",
            "darkgoldenrod", "lightsalmon", "black", "rosybrown", "blue",
            "blueviolet", "brown");
   Image pic;

    @Override
    public void start(Stage stage) {
        VBox box = new VBox();
        Scene scene = new Scene(box, 200, 200);
        stage.setScene(scene);
        stage.setTitle("ListViewSample");
        box.getChildren().addAll(list);
        VBox.setVgrow(list, Priority.ALWAYS);
        list.setItems(data);

        list.setCellFactory(listView -> new ListCell<String>() {
            public void updateItem(String friend, boolean empty) {
                super.updateItem(friend, empty);
                if (empty) {
                    setText(null);
                    setGraphic(null);
                } else {

                    imageView.setImage(image);
                    setText(friend);
                    setGraphic(imageView);
                }
            }

        });

        stage.show();
    }


    public static void main(String[] args) {
        launch(args);
    }
}`
Justine Mackay
  • 129
  • 1
  • 1
  • 10

2 Answers2

21

You do not need to create a new HBox every time you want to set an image inside a ListView. You can directly use the setCellFactory() of the ListView to achieve the same result.

This example is just an extension of the answer Image in JavaFX ListView and contains a Minimal, Complete, and Verifiable example which can be tried and tested. If you want to understand how this works, I suggest you to go through the linked question first.

Update - How to resize Images

To resize images to fit the size you want, make use of fitWidth() and fitHeight() methods of the ImageView. There are other methods like setSmooth() and setPreserveRatio() which can come in handy as well.

MCVE

import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.ListCell;
import javafx.scene.control.ListView;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

public class ListViewWithImages extends Application {

    private final Image IMAGE_RUBY  = new Image("https://upload.wikimedia.org/wikipedia/commons/f/f1/Ruby_logo_64x64.png");
    private final Image IMAGE_APPLE  = new Image("http://findicons.com/files/icons/832/social_and_web/64/apple.png");
    private final Image IMAGE_VISTA  = new Image("http://antaki.ca/bloom/img/windows_64x64.png");
    private final Image IMAGE_TWITTER = new Image("http://files.softicons.com/download/social-media-icons/fresh-social-media-icons-by-creative-nerds/png/64x64/twitter-bird.png");

    private Image[] listOfImages = {IMAGE_RUBY, IMAGE_APPLE, IMAGE_VISTA, IMAGE_TWITTER};

    @Override
    public void start(Stage primaryStage) throws Exception {

        ListView<String> listView = new ListView<String>();
        ObservableList<String> items =FXCollections.observableArrayList (
                "RUBY", "APPLE", "VISTA", "TWITTER");
        listView.setItems(items);

        listView.setCellFactory(param -> new ListCell<String>() {
            private ImageView imageView = new ImageView();
            @Override
            public void updateItem(String name, boolean empty) {
                super.updateItem(name, empty);
                if (empty) {
                    setText(null);
                    setGraphic(null);
                } else {
                    if(name.equals("RUBY"))
                        imageView.setImage(listOfImages[0]);
                    else if(name.equals("APPLE"))
                        imageView.setImage(listOfImages[1]);
                    else if(name.equals("VISTA"))
                        imageView.setImage(listOfImages[2]);
                    else if(name.equals("TWITTER"))
                        imageView.setImage(listOfImages[3]);
                    setText(name);
                    setGraphic(imageView);
                }
            }
        });
        VBox box = new VBox(listView);
        box.setAlignment(Pos.CENTER);
        Scene scene = new Scene(box, 200, 200);
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    public static void main(String[] args) {
        launch(args);
    }
}

OUTPUT

enter image description here

Community
  • 1
  • 1
ItachiUchiha
  • 36,135
  • 10
  • 122
  • 176
  • Thank you very much this is what I need. I need to learn how to do it then implement it with the current project I am working. Thanks for the people that help me here I hope you guys keep on helping other people here! – Justine Mackay Nov 08 '15 at 11:20
  • well I wonder I am loading the images to my machine not in the web when I change it to something like this Image image = new Image(Main.class.getResourceAsStream("bell.jpg")); the image size is really big I wonder how I can resize it smaller. – Justine Mackay Nov 08 '15 at 12:25
  • 1
    You can leave it to the ImageView. Use [fitWidth()](https://docs.oracle.com/javase/8/javafx/api/javafx/scene/image/ImageView.html#fitWidthProperty) and [fitHeight()](https://docs.oracle.com/javase/8/javafx/api/javafx/scene/image/ImageView.html#fitHeightProperty) on the ImageView. There are other methods like [setSmooth()](https://docs.oracle.com/javase/8/javafx/api/javafx/scene/image/ImageView.html#setSmooth-boolean-) and [setPreserveRatio()](https://docs.oracle.com/javase/8/javafx/api/javafx/scene/image/ImageView.html#setPreserveRatio-boolean-) to help you. – ItachiUchiha Nov 08 '15 at 12:40
  • @JustineMackay You can load the images from anywhere you like. I have used the web links because they can be copied and tried on any machine, whereas if I would have used the links local to my machine, you will have to make changes to the code to see it in action :) – ItachiUchiha Nov 08 '15 at 13:03
  • setFitHeight and setFitWidth works like a charm! Thanks again! – Justine Mackay Nov 08 '15 at 13:04
  • Actually I am attempting to create a standalone application which is chat based Educational Module. I have used Java because I want it also to implement at Andriod. So the images must be at the local machine like if the user wants to change the picture they can load a new pic. Well thanks again you save me from so much time studying this issue ^^, – Justine Mackay Nov 08 '15 at 13:14
  • I already did, I think it has something to do with my internet connection when I reload it it doesn't accept. sorry about it >, – Justine Mackay Nov 08 '15 at 13:18
  • imageView.resize(width, height); to resize image works for me. – Ronny K Mar 30 '18 at 02:32
  • Is it possible to do this keeping the radio button that shows what item is selected ? (CheckListView) – lubrum Apr 08 '22 at 17:25
1

In addition to my comment I will show here some code, that is working for me:

private void setListEntry(ListCell<Label> listCell, Label label) {

        Image img = loadLableIcon(label);

        GridPane row = new GridPane();
        row.setHgap(15);
        row.setVgap(15);

        ColumnConstraints col1 = new ColumnConstraints();
        col1.setPercentWidth(90);
        ColumnConstraints col2 = new ColumnConstraints();
        col2.setPercentWidth(10);

        ImageView icon = new ImageView(img);

        javafx.scene.control.Label name = new javafx.scene.control.Label(label.getName());
        name.setMinWidth(120d);

        javafx.scene.control.Label amount = new javafx.scene.control.Label("" + label.getSize());

        HBox iconAndName = new HBox(10);
        iconAndName.setAlignment(Pos.CENTER_LEFT);
        iconAndName.getChildren().addAll(icon, name);

        row.add(iconAndName, 0, 0);
        row.add(amount, 1, 0);

        row.getColumnConstraints().addAll(col1, col2);

        listCell.setGraphic(row);
    }

Please note: I'm not an expert in JavaFX, so I am not sure if it's best practise or not.

Martin Pfeffer
  • 12,471
  • 9
  • 59
  • 68
  • Thanks for helping me! I am not also a expert in JavaFx but I'm trying to improve myself with programming. Can you update your code above with the whole code? I don't know how to implement it with a new code. – Justine Mackay Nov 08 '15 at 09:34