JavaFX:使用 Filechooser 移动文件后图像未显示在 ImageView 中

JavaFX: Image not displaying in ImageView after moving file using Filechooser

在我的 JavaFX GUI 中,允许用户编辑他们的帖子,这涉及将现有图像更改为用户上传的图像。这就是下面显示的函数的用武之地。

postImage 是我从 FXML 文件中引用的 ImageView - @FXML private ImageView postImage;

private void uploadImage(ActionEvent actionEvent) {
        // Create fileChooser
        FileChooser fileChooser = new FileChooser();
        FileChooser.ExtensionFilter extFilterImages = new FileChooser.ExtensionFilter("Image files (*.jpg)", "*.JPG", "*.PNG");
        fileChooser.getExtensionFilters().addAll(extFilterImages);

        // open dialog to have user select an image from the file system
        File selectedFile = fileChooser.showOpenDialog(title.getScene().getWindow());

        if (selectedFile != null) {
            System.out.println("File selected:" + selectedFile);
            System.out.println("Selected Image: " + selectedFile.getName());

            Path source = FileSystems.getDefault().getPath(selectedFile.getPath());
            String fileExtension = selectedFile.getName().substring(selectedFile.getName().lastIndexOf("."));
            String imagePath = "newImageUploaded" + fileExtension;
            Path destination = FileSystems.getDefault().getPath("resources/images/" + imagePath);

            System.out.println("Source: " + source);
            System.out.println("Destination: " + destination);

            // moving the uploaded image to the resources folder
            try {
                Files.copy(source, destination, StandardCopyOption.REPLACE_EXISTING);
            } catch (IOException ioException) {
                ioException.printStackTrace();
                System.out.println("Exception Caught");
            }

            System.out.println("Changing image: " + imagePath);

            // Set the uploaded image in the ImageView in GUI.
            postImage.setImage(new Image("/images/" + imagePath)); // error on this line: PostDetailsController.java:326

        }

    }

当此功能为运行时,图像移动成功并出现在我的资源文件夹中。但是,应该更新我的图像的最后一行 postImage.setImage(new Image("/images/" + imagePath)); 给了我以下错误:

File selected:/Users/vaishnavinaik/Downloads/shoes.jpg
Selected Image: shoes.jpg
Source: /Users/vaishnavinaik/Downloads/shoes.jpg
Destination: resources/images/newImageUploaded.jpg
Changing image: newImageUploaded.jpg
Exception in thread "JavaFX Application Thread" java.lang.IllegalArgumentException: Invalid URL: Invalid URL or resource not found
    at javafx.graphics/javafx.scene.image.Image.validateUrl(Image.java:1107)
    at javafx.graphics/javafx.scene.image.Image.<init>(Image.java:617)
    at controller.PostDetailsController.uploadImage(PostDetailsController.java:326)
    at javafx.base/com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:86)
    at javafx.base/com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:238)
    at javafx.base/com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191)
    at javafx.base/com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59)
    at javafx.base/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
    at javafx.base/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
    at javafx.base/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
    at javafx.base/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
    at javafx.base/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
    at javafx.base/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
    at javafx.base/com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
    at javafx.base/com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:49)
    at javafx.base/javafx.event.Event.fireEvent(Event.java:198)
    at javafx.graphics/javafx.scene.Node.fireEvent(Node.java:8879)
    at javafx.controls/javafx.scene.control.Button.fire(Button.java:200)
    at javafx.controls/com.sun.javafx.scene.control.behavior.ButtonBehavior.mouseReleased(ButtonBehavior.java:206)
    at javafx.controls/com.sun.javafx.scene.control.inputmap.InputMap.handle(InputMap.java:274)
    at javafx.base/com.sun.javafx.event.CompositeEventHandler$NormalEventHandlerRecord.handleBubblingEvent(CompositeEventHandler.java:218)
    at javafx.base/com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:80)
    at javafx.base/com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:238)
    at javafx.base/com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191)
    at javafx.base/com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59)
    at javafx.base/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
    at javafx.base/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
    at javafx.base/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
    at javafx.base/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
    at javafx.base/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
    at javafx.base/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
    at javafx.base/com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
    at javafx.base/com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:54)
    at javafx.base/javafx.event.Event.fireEvent(Event.java:198)
    at javafx.graphics/javafx.scene.Scene$MouseHandler.process(Scene.java:3851)
    at javafx.graphics/javafx.scene.Scene$MouseHandler.access00(Scene.java:3579)
    at javafx.graphics/javafx.scene.Scene.processMouseEvent(Scene.java:1849)
    at javafx.graphics/javafx.scene.Scene$ScenePeerListener.mouseEvent(Scene.java:2588)
    at javafx.graphics/com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:397)
    at javafx.graphics/com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:295)
    at java.base/java.security.AccessController.doPrivileged(Native Method)
    at javafx.graphics/com.sun.javafx.tk.quantum.GlassViewEventHandler.lambda$handleMouseEvent(GlassViewEventHandler.java:434)
    at javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock(QuantumToolkit.java:390)
    at javafx.graphics/com.sun.javafx.tk.quantum.GlassViewEventHandler.handleMouseEvent(GlassViewEventHandler.java:433)
    at javafx.graphics/com.sun.glass.ui.View.handleMouseEvent(View.java:556)
    at javafx.graphics/com.sun.glass.ui.View.notifyMouse(View.java:942)
    at javafx.graphics/com.sun.glass.ui.mac.MacView.notifyMouse(MacView.java:127)
Caused by: java.lang.IllegalArgumentException: Invalid URL or resource not found
    at javafx.graphics/javafx.scene.image.Image.validateUrl(Image.java:1099)
    ... 46 more

难不成在执行postImage.setImage(new Image("/images/" + imagePath));语句的时候,移动还没有完成?将图像设置到 imageView 时我做错了什么吗?

Image 构造函数期望将代表 URLString 传递给它。如 documentation

中所述

If the passed string is not a valid URL, but a path instead, the Image is searched on the classpath in that case.

因此,您在这里有效地尝试做的是在运行时修改类路径的内容;这是不可行的(例如,如果应用程序是来自 jar 文件的 运行,这在生产中几乎肯定是正确的,您将不得不在运行时修改该 jar 文件的内容,这可能是不可能的).

假设此处的目的是保留图像以便下次用户运行应用程序时可用,通常的方法是将图像复制到用户系统上的一个文件夹中,该文件夹用于存储用户特定的您的应用程序的数据。 (替代方法可能是将图像数据存储在本地或远程数据库中,具体取决于应用程序。)一个常见的方案是使用名称以 . 开头并包含图像名称的文件夹应用程序,并且位于用户的主目录中:

Path applicationDataPath = Paths.get(System.getProperty("user.home"), ".my-application");
Files.createDirectories(applicationDataPath);

现在你可以做

Path destination = applicationDataPath.resolve("newImageUploaded"+fileExtension);

try {

    Files.copy(source, destination, StandardCopyOption.REPLACE_EXISTING);

    System.out.println("Changing image: " + imagePath);

    // Set the uploaded image in the ImageView in GUI.
    postImage.setImage(new Image(destination.toUri().toURL().toExternalForm())); 

} catch (IOException ioException) {
    ioException.printStackTrace();
    System.out.println("Exception Caught");
}

你也可以很容易地,例如,在应用程序启动时检查该文件是否存在,并根据需要显示图像等。