javaimagejavafxobservablelist

JavaFX - Add a horizontal list of images dynamically and make it selectable


I'm new to java and javafx so I am still learning. I can get the images to display on a horizontal line but I can't make it selectable. I'm not sure if I am using the wrong layout or if I am missing something in the code.

Code

  List<Image> movieImages= movieDetails.movieImages(jsonRequest);
    ObservableList<Image> movies = FXCollections.observableList(movieImages);
    for(int i=0; i < movies.size(); i++){
        ImageView imageView;
        imageView = new ImageView(movies.get(i));
        hboxFanart.getChildren().addAll(imageView);
    }

FMXL

<Tab closable="false" text="Fanart">
            <ScrollPane>
                <HBox fx:id="hboxFanart" spacing="10">
                </HBox>
            </ScrollPane>
</Tab>

Solution

  • I altered @ItachiUchiha answer from here

    As @James_D suggests, try using a ListView. Set the ListView orientation to horizontal.

    import javafx.application.Application;
    import javafx.collections.FXCollections;
    import javafx.collections.ObservableList;
    import javafx.geometry.Orientation;
    import javafx.geometry.Pos;
    import javafx.scene.Scene;
    import javafx.scene.control.Label;
    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.StackPane;
    import javafx.scene.layout.VBox;
    import javafx.stage.Stage;
    
    public class App 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 final Image[] listOfImages = {IMAGE_RUBY, IMAGE_APPLE, IMAGE_VISTA, IMAGE_TWITTER};
    
        @Override
        public void start(Stage primaryStage) throws Exception
        {
            Label lblCurrentlySelected = new Label();
            StackPane stackPane = new StackPane(lblCurrentlySelected);
    
            ListView<String> listView = new ListView();
            listView.setMaxHeight(100);
            ObservableList<String> items = FXCollections.observableArrayList(
                    "RUBY", "APPLE", "VISTA", "TWITTER");
            listView.setItems(items);
            listView.setOrientation(Orientation.HORIZONTAL);
            listView.setCellFactory(param -> new ListCell<String>()
            {
                private final ImageView imageView = new ImageView();
    
                @Override
                public void updateItem(String name, boolean empty)
                {
                    super.updateItem(name, empty);
                    if (empty) {
                        setText(null);
                        setGraphic(null);
                    }
                    else {
                        switch (name) {
                            case "RUBY" ->
                                imageView.setImage(listOfImages[0]);
                            case "APPLE" ->
                                imageView.setImage(listOfImages[1]);
                            case "VISTA" ->
                                imageView.setImage(listOfImages[2]);
                            case "TWITTER" ->
                                imageView.setImage(listOfImages[3]);
                            default -> {
                            }
                        }
                        setText(name);
                        setGraphic(imageView);
                    }
                }
            });
            listView.getSelectionModel().selectedItemProperty().addListener((ov, oldItem, newItem) -> {
                if (newItem != null) {
                    System.out.println("Selected: " + newItem);
                    lblCurrentlySelected.setText(newItem);
                }
            });
    
            VBox.setVgrow(stackPane, Priority.ALWAYS);
            VBox box = new VBox(listView, stackPane);
            box.setAlignment(Pos.CENTER);
            Scene scene = new Scene(box, 500, 500);
            primaryStage.setScene(scene);
            primaryStage.show();
        }
    
        public static void main(String[] args)
        {
            launch(args);
        }
    }
    

    Some links seem to be broken, but the ideas behind this are the same.

    Output enter image description here

    Based on your comment, I created an example using a POJO. That's assuming I understand what you are asking. The POJO keeps up with the name and image. That eliminates the need to have the Switch-Statement.

    Code

    import javafx.application.Application;
    import javafx.collections.FXCollections;
    import javafx.collections.ObservableList;
    import javafx.geometry.Orientation;
    import javafx.geometry.Pos;
    import javafx.scene.Scene;
    import javafx.scene.control.Label;
    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.StackPane;
    import javafx.scene.layout.VBox;
    import javafx.stage.Stage;
    
    public class App 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 final Image[] listOfImages = {IMAGE_RUBY, IMAGE_APPLE, IMAGE_VISTA, IMAGE_TWITTER};
        private final ObservableList<MyItem> listViewItems = FXCollections.observableArrayList();
    
        @Override
        public void start(Stage primaryStage) throws Exception
        {
            listViewItems.add(new MyItem("Ruby", IMAGE_RUBY));
            listViewItems.add(new MyItem("Apple", IMAGE_APPLE));
            listViewItems.add(new MyItem("Vista", IMAGE_VISTA));
            listViewItems.add(new MyItem("Twitter", IMAGE_TWITTER));
    
            Label lblCurrentlySelected = new Label();
            StackPane stackPane = new StackPane(lblCurrentlySelected);
    
            ListView<MyItem> listView = new ListView();
            listView.setMaxHeight(100);
            listView.setItems(listViewItems);
            listView.setOrientation(Orientation.HORIZONTAL);
            listView.setCellFactory(param -> {
                return new ListCell<MyItem>()
                {
                    private final ImageView imageView = new ImageView();
    
                    @Override
                    public void updateItem(MyItem myItem, boolean empty)
                    {
                        super.updateItem(myItem, empty);
                        if (empty || myItem == null) {
                            setText(null);
                            setGraphic(null);
                        }
                        else {
                            setText(myItem.getName());
                            imageView.setImage(myItem.getImage());
                            setGraphic(imageView);
                        }
                    }
                };
            });
            listView.getSelectionModel().selectedItemProperty().addListener((ov, oldItem, newItem) -> {
                if (newItem != null) {
                    System.out.println("Selected: " + newItem.getName());
                    lblCurrentlySelected.setText(newItem.getName());
                }
            });
    
            VBox.setVgrow(stackPane, Priority.ALWAYS);
            VBox box = new VBox(listView, stackPane);
            box.setAlignment(Pos.CENTER);
            Scene scene = new Scene(box, 500, 500);
            primaryStage.setScene(scene);
            primaryStage.show();
        }
    
        public static void main(String[] args)
        {
            launch(args);
        }
    }
    

    POJO

    import javafx.scene.image.Image;
    
    /**
     *
     * @author Sedrick(sedj601)
     */
    public class MyItem
    {
    
        private String name;
        private Image image;
    
        public MyItem(String name, Image image)
        {
            this.name = name;
            this.image = image;
        }
    
        public Image getImage()
        {
            return image;
        }
    
        public void setImage(Image image)
        {
            this.image = image;
        }
    
        public String getName()
        {
            return name;
        }
    
        public void setName(String name)
        {
            this.name = name;
        }
    }