JavaFX。使用Filechooser移动文件后,ImageView中不显示图像。

问题描述 投票:0回答:1

在我的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.access$1200(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$2(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的时候是不是做错了什么?

java javafx imageview filechooser
1个回答
0
投票

Image 构造函数期待一个 String 代表 URL 要传递给它。正如《公约》中所说 文件

如果传递的字符串不是一个有效的URL,而是一个路径,在这种情况下,将在classpath上搜索Image。

所以你在这里要做的实际上是在运行时修改classpath的内容;这是不可行的(例如,如果应用程序从一个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");
}

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

© www.soinside.com 2019 - 2024. All rights reserved.