因此,正如文章的标题所述,我要求提供一种方法,可以说是我使用FileChooser上传到项目中的目录的文件。
更具体地说,我上传的图片,我想保存在我的项目,以便我可以在未来使用它们。下面是一个示例代码:
主计长:
package org.example;
import javafx.fxml.FXML;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.stage.FileChooser;
import java.io.File;
public class PrimaryController {
@FXML
private ImageView image;
@FXML
void handleUploadImage() {
FileChooser fileChooser = new FileChooser();
fileChooser.getExtensionFilters().addAll(new FileChooser.ExtensionFilter("Image Files", "*.jpg", "*.jpeg", "*.png", "*.svg"));
File file = fileChooser.showOpenDialog(null);
if (file != null) {
image.setImage(new Image(String.valueOf(file)));
} else {
System.out.println("It's null");
}
}
}
FXML:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.Cursor?>
<?import javafx.scene.image.Image?>
<?import javafx.scene.image.ImageView?>
<?import javafx.scene.layout.AnchorPane?>
<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" style="-fx-background-color: linear-gradient(to right, #1c92d2, #f2fcfe);" xmlns="http://javafx.com/javafx/18" xmlns:fx="http://javafx.com/fxml/1" fx:controller="org.example.PrimaryController">
<children>
<ImageView fx:id="image" fitHeight="200.0" fitWidth="200.0" layoutX="200.0" layoutY="100.0" onMouseClicked="#handleUploadImage" pickOnBounds="true" preserveRatio="true">
<image>
<Image url="@../../images/upload.png" />
</image>
<cursor>
<Cursor fx:constant="HAND" />
</cursor>
</ImageView>
</children>
</AnchorPane>
我的目录:
我想把图像保存在/resources/images
中。我怎样才能做到呢?
发布于 2022-05-19 22:11:21
背景信息
文件不是“上传”的。该术语通常用于操作,例如将文件发送到托管云服务或FTP站点。您的代码选择一个通过本地机器的文件系统可用的文件。那你就想用它做点什么。可能是在本地复制到另一个位置。我想你可能会选择把这个过程称为“上传”,但是,对我来说,这个术语似乎并不适合。
通常,当部署JavaFX应用程序时,它的所有代码和资源都将打包在一起,例如在jar文件、安装程序或jlink映像中。项目源代码的资源目录将不存在,但其内容将被复制到包中。在运行时向该位置添加额外资源是一种未定义的操作,因为您并不真正知道这些资源将流向何处。
建议的替代方案:保存到已知的本地文件位置
您可能要做的是将文件复制到机器上一个众所周知的位置,并从那里访问它。这样做的一种方法是在用户的主目录下创建一个目录(例如.myapp
),将所选的文件复制到该目录中,然后根据需要从该目录读取和写入文件。您可以使用java系统属性确定用户的主目录。
替代方案:使用Preferences API
您可以使用Java首选项API,而不是使用用户主目录下的自定义应用程序目录。
此包允许应用程序存储和检索用户和系统首选项和配置数据。此数据持久存储在依赖于实现的备份存储中。有两个独立的偏好节点树,一个用于用户首选项,另一个用于系统首选项。
关于如何做到这一点的详细讨论超出了这个答案的范围,但是在它周围有许多关于网络的教程。
在JavaFX应用程序中使用JavaFX的一个例子是makery教程。
FAQ
这没有任何意义。我必须做什么,如果我愿意允许用户上传一个图像,然后将图像保存在我的个人电脑或我的项目?
想必,您的“项目”就是您在问题中显示的源代码目录。如前所述,该目录在本地开发环境之外的运行时不可用。所以您不能在运行时将文件保存到项目中,因为它将不存在。相反,你需要“把图像保存在我的电脑上的某个地方”。这样做的一种方法是遵循我提供的关于将图像放置在应用程序特定子目录中的建议,该子目录是应用程序在用户的主目录中创建的。
这个解决方案在全球范围内有效吗?就像这个项目不只是为了我,这意味着它会被发送给一些人,所以他们将不会有我保存的文件目录。
他们将有一个用户目录,因为这是OSes的工作方式。它可以从我链接的系统属性中获得。如果您按照需要在用户目录下创建和使用一个特定于应用程序的子目录的路径,那么您可以确信所需的目录将存在。OSes中对于不同位置的存储还有其他约定,但我建议您只使用用户目录下的应用程序特定目录,除非您需要做其他事情。还有其他选项,比如上传到云端托管图像服务,但除非您需要,否则不要这样做。
另外,在这个项目中,我把我使用的所有图像放在一个目录中,例如/resources/映像,我需要将图像保存在其中。
正如所解释的,您不能在运行时动态地这样做。您需要将动态添加的映像放到其他地方(例如,在用户本地目录、云服务、共享数据库等下)。你需要从同一个地方读那些文件。如果将它们放在用户目录下,则可以使用文件URL或文件API而不是getResource来读取和写入文件。
示例应用程序
此应用程序使用用户的主目录存储选定的化身图像。
应用程序将使用应用程序附带的应用程序资源中的默认化身。如果用户选择要使用的新图像,则可以更改默认化身。
正在使用的当前化身处理存储在<user.home>/.avatar/avatar.png
中的文件。
这个答案提供了用于默认图像的自定义图标图像:
这个解决方案可能与您所需要的不同,您可能需要为任意图像集提供文件上传服务,比如相册,而不是像化身这样的单个图像。但是,希望这里显示的信息为您提供了一个具体的示例,说明如何继续解决您的确切问题。
uploadCustomAvatar
方法在AvatarService
中以InputStream
作为参数。因此,如果需要,可以采用该方法从本地图像文件以外的另一个位置(例如,web URL)来源自定义图像。
默认化身
上传自定义化身
AvatarApp.java
import javafx.application.*;
import javafx.geometry.*;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.image.*;
import javafx.scene.layout.VBox;
import javafx.stage.FileChooser;
import javafx.stage.Stage;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.*;
public class AvatarApp extends Application {
private static final String APP_DIR = ".avatar";
private AvatarService avatarService;
@Override
public void init() {
LocalStorage localStorage = new LocalStorage(APP_DIR);
avatarService = new AvatarService(localStorage);
}
@Override
public void start(Stage stage) throws Exception {
ImageView avatar = new ImageView(avatarService.getAvatarImage());
avatar.imageProperty().bind(avatarService.avatarImageProperty());
avatar.setFitWidth(AvatarService.DIMENSIONS);
avatar.setFitHeight(AvatarService.DIMENSIONS);
avatar.setPreserveRatio(true);
Button changeAvatarButton = new Button("Change...");
changeAvatarButton.setOnAction(e -> uploadCustomAvatar(stage));
VBox layout = new VBox(10, avatar, changeAvatarButton);
layout.setStyle("-fx-background-color: linen; -fx-font-size: 16px");
layout.setAlignment(Pos.CENTER);
layout.setPadding(new Insets(10));
stage.setScene(new Scene(layout));
stage.show();
}
private void uploadCustomAvatar(Stage owner) {
FileChooser fileChooser = new FileChooser();
fileChooser.setTitle("Choose your avatar");
fileChooser.getExtensionFilters().addAll(
new FileChooser.ExtensionFilter(
"PNG Image Files", "*.png"
)
);
File selectedFile = fileChooser.showOpenDialog(owner);
if (selectedFile != null) {
try (
InputStream inputStream = new BufferedInputStream(
Files.newInputStream(selectedFile.toPath())
)
) {
avatarService.uploadCustomAvatar(inputStream);
} catch (IOException ex) {
System.out.println("Unable to upload avatar");
ex.printStackTrace();
}
}
}
public static void main(String[] args) {
launch(args);
}
}
AvatarService.java
import javafx.application.Platform;
import javafx.beans.property.ReadOnlyObjectProperty;
import javafx.beans.property.ReadOnlyObjectWrapper;
import javafx.scene.image.Image;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
import java.util.Objects;
class AvatarService {
public static final double DIMENSIONS = 96;
private static final String DEFAULT_AVATAR_RESOURCE = "Dragon-icon.png";
private static final String AVATAR_FILENAME = "avatar.png";
private final Path avatarPath;
private final ReadOnlyObjectWrapper<Image> avatarImage = new ReadOnlyObjectWrapper<>();
public AvatarService(LocalStorage localStorage) {
avatarPath = localStorage.getLocalStoragePath().resolve(AVATAR_FILENAME);
if (!Files.exists(avatarPath)) {
copyDefaultAvatar();
}
refreshImage();
}
private void copyDefaultAvatar() {
try {
Files.copy(
Objects.requireNonNull(
AvatarApp.class.getResourceAsStream(
DEFAULT_AVATAR_RESOURCE
)
),
avatarPath
);
} catch (IOException e) {
System.out.println("Unable to initialize default avatar");
e.printStackTrace();
Platform.exit();
}
}
public void uploadCustomAvatar(InputStream inputStream) {
try {
Files.copy(
inputStream,
avatarPath,
StandardCopyOption.REPLACE_EXISTING
);
refreshImage();
} catch (IOException e) {
System.out.println("Unable to upload custom avatar");
e.printStackTrace();
}
}
public Image getAvatarImage() {
return avatarImage.get();
}
public ReadOnlyObjectProperty<Image> avatarImageProperty() {
return avatarImage.getReadOnlyProperty();
}
private void refreshImage() {
avatarImage.set(
new Image(
"file:" + avatarPath.toAbsolutePath()
)
);
}
}
LocalStorage.java
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
class LocalStorage {
private Path localStoragePath;
public LocalStorage(String name) {
try {
String userDir = System.getProperty("user.home");
localStoragePath = Paths.get(userDir, name);
if (!Files.isDirectory(localStoragePath)) {
Files.createDirectory(localStoragePath);
}
} catch (IOException ex) {
System.out.println("Unable to initialize local storage");
ex.printStackTrace();
Platform.exit();
}
}
public Path getLocalStoragePath() {
return localStoragePath;
}
}
https://stackoverflow.com/questions/72294934
复制相似问题