我已经成功地在同一个窗格上绘制了两个图形(条形图和折线图)。
我试图实现一个保存按钮,当点击它时,将结果图像(带轴)写入我保存的bmp图像。
代码运行,我得到一个肯定的警告,并创建了一个图像文件。然而,生成的图像文件是空的(0字节)。
@FXML // fx:id="graph"
private Pane graph; // Value injected by FXMLLoader
@FXML // fx:id="saveButton"
private Button saveButton; // Value injected by FXMLLoader
// ...
@FXML
void clickSave(ActionEvent event) {
Stage yourStage = (Stage) saveButton.getScene().getWindow();
FileChooser fileChooser = new FileChooser();
fileChooser.setInitialDirectory(new File("Path\\With\\Spaces"));
fileChooser.getExtensionFilters().add(new FileChooser.ExtensionFilter("BMP Files", "*.bmp"));
// Show save dialog
File file = fileChooser.showSaveDialog(yourStage);
if (file != null) {
if (!file.exists()) {
try {
Files.createFile(file.toPath());
} catch (IOException e) {
e.printStackTrace(); // Handle the exception
}
}
WritableImage writableImage = graph.snapshot(new SnapshotParameters(), null);
BufferedImage bufferedImage = SwingFXUtils.fromFXImage(writableImage, null);
try {
ImageIO.write(bufferedImage, "BMP", file);
// Inform the user about the successful save
Alert alert = new Alert(Alert.AlertType.INFORMATION);
alert.setTitle("File Saved");
alert.setHeaderText(null);
alert.setContentText("The file has been saved successfully.");
alert.showAndWait();
} catch (IOException e) {
e.printStackTrace();
// Inform the user about the error
Alert alert = new Alert(Alert.AlertType.ERROR);
alert.setTitle("Error");
alert.setHeaderText(null);
alert.setContentText("An error occurred while saving the file.");
alert.showAndWait();
}
}
}
字符串
编辑:遵循@James_D的评论建议,我将代码更改为以下内容,但问题仍然存在。
@FXML
void clickSave(ActionEvent event) {
Stage stage = (Stage) saveButton.getScene().getWindow();
FileChooser fileChooser = new FileChooser();
fileChooser.setInitialDirectory(new File("Path\\With\\Spaces"));
fileChooser.getExtensionFilters().add(new FileChooser.ExtensionFilter("BMP Files", "*.bmp"));
// Show save dialog
File file = fileChooser.showSaveDialog(stage);
if (file != null) {
WritableImage writableImage = graph.snapshot(new SnapshotParameters(), null);
BufferedImage bufferedImage = SwingFXUtils.fromFXImage(writableImage, null);
try {
ImageIO.write(bufferedImage, "BMP", file);
if (!file.exists()) {
Files.createFile(file.toPath());
}
// Inform the user about the successful save
Alert alert = new Alert(Alert.AlertType.INFORMATION);
alert.setTitle("File Saved");
alert.setHeaderText(null);
alert.setContentText("The file has been saved successfully.");
alert.showAndWait();
} catch (IOException e) {
e.printStackTrace();
// Inform the user about the error
Alert alert = new Alert(Alert.AlertType.ERROR);
alert.setTitle("Error");
alert.setHeaderText(null);
alert.setContentText("An error occurred while saving the file.");
alert.showAndWait();
}
}
}
型
2条答案
按热度按时间4sup72z81#
非常感谢@Slaw和this answer。
SwingFXUtils函数返回
TYPE_INT_ARGB_PRE
类型的图像。只有TYPE_INT_RGB
类型的图像可以写入.bmp文件,否则ImageIO.write(bufferedImage, "BMP", file);
返回false
。因此,必须完成从TYPE_INT_ARGB_PRE
到TYPE_INT_RGB
的适当转换。下面的块显示了更新后的代码,其中现在包括转换。字符串
vwoqyblh2#
问题
ImageIO::write
方法将返回false:如果没有找到适当写入器
在这种情况下不会抛出异常。
根据ImageIO.write bmp does not work问答,内置的BMP图像写入器要求图像的类型为
TYPE_INT_RGB
。如果BufferedImage
不具有该类型,则对write
的调用将无法找到“适当的写入器”,并将返回false,这意味着没有图像写入文件。看看
SwingFXUtils::fromFXImage
的实现,返回图像的类型取决于源图像的格式以及您是否传入了自己的BufferedImage
。从一些经验来看,通过拍摄节点快照创建的JavaFX图像的类型似乎是TYPE_INT_ARGB_PRE
。不幸的是,这是错误的类型,因此在你的例子中没有图像被写入文件。但是因为你没有检查返回值,你错误地向用户报告成功。解决方案
要解决这个问题,您需要强制
BufferedImage
具有TYPE_INT_RGB
类型。这里有三种不同的方法。预先创建
BufferedImage
所需类型如果你能保证JavaFX
Image
是不透明的,我不确定关于快照,那么可以说最简单的方法是传递你自己预先创建的BufferedImage
。例如:字符串
手动复制像素数据
您可以手动将像素从
PixelReader
复制到BufferedImage
。例如:型
应该可以将像素读取为ARGB,因为在这种情况下,当写入
BufferedImage
时,alpha通道只是“丢失”。将
BufferedImage
复制到新的BufferedImage
中,复制类型为BufferedImage
这种方法基于this answer到ImageIO.write bmp does not work。
型
注意事项
BufferedImage
,都可以并且应该在后台线程上完成。然后,无论正常还是异常,都可以在 *JavaFX应用程序线程 * 上对后台工作完成做出React(这是您显示警报、重新启用控件等的地方)。有关更多信息,请参阅JavaFX中的并发和
javafx.concurrent
包。javafx.concurrent.Task
类特别适合这种情况。这不是你在这里的主要问题 [...],但要注意的是,当在图表上调用快照时,通常你想将图表中的
animate
设置为false,以便快照将捕获图表的最终状态,而不是在图表更改动画完成之前的状态。还有:
snapshot
文档中提到:“* 当拍摄正在动画化的场景的快照时,无论是由应用程序显式地还是隐式地(例如图表动画),快照都将基于拍摄快照时场景图形的状态进行渲染,并且不会反映任何后续的动画更改 *”。