How to add images to a ListView

2020-05-01 09:37发布

问题:

I've been reading documents for the last 8 hours and found nothing that could help me. Vaguely yes, but no code is working becuase it keeps saying "image url not found" and throws the exception. However I have other projects and never had this issue.

So, there's one class that contains months like so:

public enum Month{JAN(1, "img.png",...DEC(12, "img.png");
private final int monthValue;
private final String imgName;

private Month(int monthValue, String imgName){
this.monthValue = monthValue;
this.imgName = imgName;
}

public int getMonth(){
return monthValue;
}

public String getImage(){
return imgName;} 
}

So far, so good. I can even test it in console and works fine and also sorts by value. Now when I try to add images from resources there's the problem I mentioned before: the url is not found. However, I can do a ImageView with only 1 value of the image, using the path goes from "C:\...\resources\monthImg.png" but I work with other person and eachtime I send it online he must change the image directory as well. Takes much time.

Now, what I've been trying to do is to get 12 images and set them to this enum in the main project class. So I can then assign to nodes and work GUI.

My approach was to follow this thread: JavaFx : How to put ImageView inside ListView However, it uses setCellFactory which I am pretty sure you can do this without that method and less code lines.

I have two packages called "main" (which contains the main class and the month class with its constructors and methods) and a resources package also called "main" in a different folder (which contains all images). Remember that it works if I use the whole full path from C:\ but I'd also like to have it started in the project itself to send it to my friend.

What would be the approach look like so I can get these images with value stack with each other in descendant values inside a VBox like the example in the link above?

Note: The project is to make those images look like a calendar stacked up with drag and drop options (which I know to do). Thanks.

回答1:

Try to solve the issues in smaller pieces, a step by step approach.
You can start by getting the list view display the images you want. Using hot linked images makes the code more of an mre and makes helping and testing easy and efficient:

import java.util.stream.Stream;
import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.geometry.Orientation;
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.TilePane;
import javafx.stage.Stage;

public class FxMain extends Application {

    @Override
    public void start(Stage primaryStage) {

        MonthListCell[] listCell = Stream.of(Month.values()).map(MonthListCell::new).toArray(MonthListCell[]::new);
        ObservableList<MonthListCell> items =FXCollections.observableArrayList (listCell);
        ListView<MonthListCell> listView = new ListView<>(items);
        primaryStage.setScene(new Scene(listView));
        primaryStage.sizeToScene();
        primaryStage.show();
    }

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

enum Month{

    JAN(1,"https://cdn3.iconfinder.com/data/icons/softwaredemo/PNG/64x64/Circle_Green.png"),
    FEB(2,"https://cdn3.iconfinder.com/data/icons/softwaredemo/PNG/64x64/Circle_Red.png"),
    MAR(3,"https://cdn3.iconfinder.com/data/icons/softwaredemo/PNG/64x64/Circle_Yellow.png"),
    APR(4,"https://cdn3.iconfinder.com/data/icons/softwaredemo/PNG/64x64/Circle_Blue.png"),
    MAY(5,"https://cdn3.iconfinder.com/data/icons/softwaredemo/PNG/64x64/Circle_Orange.png"),
    JUN(6,"https://cdn3.iconfinder.com/data/icons/softwaredemo/PNG/64x64/Circle_Grey.png");

    private final int monthValue;
    private final String imgName;

    private Month(int monthValue, String imgName){
        this.monthValue = monthValue;
        this.imgName = imgName;
    }

    public int getMonth(){
        return monthValue;
    }

    public String getImage(){
        return imgName;
    }
}

class MonthListCell extends ListCell<Month> {

    private final ImageView imageView;
    private final Label text; 

    MonthListCell(Month month) {
        Image image = new Image(month.getImage());
        imageView = new ImageView(image);
         //use label for text instead of setText() for better layout control 
        text = new Label(month.name());
        TilePane node = new TilePane(Orientation.VERTICAL, 5, 0, imageView, text);
        setGraphic(node);
    }

    @Override
    public void updateItem(Month month, boolean empty) {
        super.updateItem(month, empty);
        if (empty) {
            setText(null);
            setGraphic(null);
        } else {
            imageView.setImage(new Image(month.getImage()));
            text.setText(month.name());
        }
    }
}

Next try to use local resources (images) instead of the linked resources.