Using a resource folder to load images on JavaFX project using IntelIiJ

浪子不回头ぞ 提交于 2021-02-16 21:07:28

问题


I'm trying to load an image to a JavaFX project. I'm doing it by calling the absolute path Users/user/Desktop/nfc.png. Is there any way to create a resource folder inside the project and calling from it the image?

Below is my code:

package sample;

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.image.Image;
import javafx.stage.Stage;

import java.awt.Taskbar;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;



public class Main extends Application {

    @Override
    public void start(Stage primaryStage) throws Exception{
        Parent root = FXMLLoader.load(getClass().getResource("sample.fxml"));

        primaryStage.setResizable(false);

        Scene scene = new Scene(root);

        scene.getStylesheets().add("/sample/desing.css");

        primaryStage.getIcons().add(new Image("file:/Users/user/Desktop/nfc.png "));



        primaryStage.setScene(scene);
        primaryStage.show();
    }


    public static void main(String[] args)
    {
        Taskbar taskbar=Taskbar.getTaskbar();
        BufferedImage image = null;
        try {
            image = ImageIO.read(new File("/Users/user/Desktop/nfc.png"));
        } catch (IOException e) {
            e.printStackTrace();
        }
        taskbar.setIconImage(image);
        launch(args);
    }
}

I'm using IntelIJ. I've tried by creating a folder named resource on the project directory and call the image Main.class.getResource()


回答1:


Quick Solution for finding images

You see how you load the stylesheet in the preceding line by providing the string "/sample/desing.css", do the same thing for your image, e.g. new Image("/sample/nfc.png").

That assumes that the image is in the same location as your css. If it were somewhere else, e.g. under /images/ngc.png, then you would use that path. It also assumes that your build system is configured to copy the source resource files to your project output directory.

Finding images when your project is based on a build tool (e.g. maven)

If you are using a build tool such as Maven or Gradle (recommended for any medium to large size project), it will have a standard structure where your java classes are in src/main/java and your resources, such as css and images are in src/main/resources. It is automatically configured to copy the resources into your application artifact.

Finding images using IntelliJ or another IDE

You note that you are using IntelliJ, that tool (and any other major Java IDE) is intelligent enough to recognize that a project built with a build tool such as maven has a standard structure and will automatically configure an imported maven project in Idea to understand that structure, so you don't have to do anything additional.

If you are not using a recommended tool such as maven, then you can configure the project manually to copy over resources (as @egimaben defined in his answer). Manual configuration for copying resources in other IDEs will differ, so you will need to research how the IDE handles project resources to work out how to do that for such projects.

Example code to find images

So for example, if your image is in this location within your project source: src/main/resources/images/ngc.png, you can access it in your project via:

Image image = new Image("/images/nfc.png");

If you don't need a reference to the image, you can just directly reference the location from your ImageView constructor:

ImageView imageView = new ImageView("/images/nfc.png");

Relevant documentation

Read the image doc to see how images are found. Specifically, these lines show how to load images from resources on the class path:

// The image is located in default package of the classpath
Image image1 = new Image("/flower.png", true);

// The image is located in my.res package of the classpath
Image image2 = new Image("my/res/flower.png", 100, 150, false, false);

Note on explicitly using the file: protocol (don't do it)

To load from the class or module path, don't explicitly use the file: protocol, your files could be in a jar or elsewhere such as on a remote network, so the protocol needed to access them could change (a file in jar needs to be accessed using the jar: protocol, not the file: protocol). When you don't specify a protocol in your Image constructor, then the system will default to use the class loader, which already knows what protocol to use to find resources on your class path.

Troubleshooting

Place the following line in your code where you are trying to load the image:

System.out.println(getClass().getResource("<imagepath>"))

Where is the "<imagepath>" is exactly the same string you passed to the image constructer. If the call outputs null, then the image is probably not on your class path at the expected location.

If your app is packaged as a jar, run jar tvf <yourjar>.jar, replacing <yourjar> with the name of your jar file and it will list everything in the jar file. Most likely the image won't be at the location in the jar file you are trying to retrieve it from, so you will need to move it around or fix your build system to get it in the right place.

Image has error and exception properties, if it fails to load, you can query the exception and it may provide you with some more info on what went wrong, e.g.:

Image image = new Image("/images/nfc.png");
if (image.isError()) {
    System.out.println(image.getException());
}

If you use an image constructor with background loading, then the error could occur asynchronously, so you would need to monitor changes in the error property to know if an error occurred:

Image image = new Image("/images/nfc.png");
if (image.isError()) {
    System.out.println(image.getException());
} else {
    image.errorProperty().addListener((observable, oldValue, newValue) -> {
        if (image.isError()) {
            System.out.println(image.getException());
        }
    });
}



回答2:


Create a new directory at the root of the project(in the same hierarchy as src) called resources. Convert it to a source directory by right clicking on it in intellij: Right click -> Mark directory as -> Sources Root. You can then organise your resource files into packages if you please, the same way you create packages inside src. In this case you could have resources/sample/nfc.png. In your code, you can load it as below:

new Image(this.getClass().getResourceAsStream("nfc.png"));

Needless to say, you need to add error handling code, prefer to use try-with-resources.



来源:https://stackoverflow.com/questions/59218580/using-a-resource-folder-to-load-images-on-javafx-project-using-inteliij

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!