Hi all so i am attempting to create a gui where one can drag and drop images of components into a stackpane, then take this finished layout / image (of multiple uploaded images) and put it into an excel file, i figured it would be better to save a local version of that snapshoted node first on the users computer and then send it to excel but when i attempt to save a test png it does not work. Not in the sense that it doesnt work at all but once the .showSaveDialog window opens i choose .PNG as an extension then give the file a name like “test” for example and hit save no file is created.i dont know what else would be needed or if its some silly mistake(of course i dont know im fairly new to javafx so please be patient). PS i attempted to make a minimal reproducible example im sorry if it is not perfect. My controller class:
public class Main { @FXML private AnchorPane layoutPane; @FXML private Canvas layoutCanvas; @FXML private StackPane stackPane; Window mainStage; String filePath; String imageFilePath; // just to test saving a snapshot it just sets a single imageview as a child of the // stack pane when button clicked otherwise this deals with drag and drop public void dragAndDropImageView(ImageView image) { image.setOnMousePressed(new EventHandler<MouseEvent>() { @Override public void handle(MouseEvent mouseEvent) { x = image.getLayoutX() - mouseEvent.getSceneX(); y = image.getLayoutY() - mouseEvent.getSceneY(); } }); image.setOnMouseDragged(new EventHandler<MouseEvent>() { @Override public void handle(MouseEvent mouseEvent) { image.setLayoutX(mouseEvent.getSceneX() + x); image.setLayoutY(mouseEvent.getSceneY() + y); } }); stackPane.getChildren().addAll(image); } // is supposed to handle the creation of new image views on each button click public void handleImage() throws IOException { final double startingXPosition = 14; final double startingYPosition = 146; File chosenFile = fileChooser.showOpenDialog(mainStage); String imageFilePath = chosenFile.getAbsolutePath(); Image componentImage = new Image(imageFilePath); ImageView imageView = new ImageView(); imageView.setImage(componentImage); imageView.setLayoutX(startingXPosition); imageView.setLayoutY(startingYPosition); imageView.setFitWidth(154); imageView.setFitHeight(135); layoutPane.getChildren().addAll(imageView); imageView.setVisible(true); dragAndDropImageView(imageView); } //handles saving image as png and sending to excel public void exportImage() throws IOException { FileInputStream fis = new FileInputStream(filePath); //String imageFilePath = imageFile.getAbsolutePath(); XSSFWorkbook workBook = new XSSFWorkbook(fis); XSSFSheet sheet = workBook.getSheet("Tooling Layout"); WritableImage wi = new WritableImage(1080,790); stackPane.snapshot(null, wi); BufferedImage bImage = SwingFXUtils.fromFXImage(wi, null); FileChooser saveFile = new FileChooser(); FileChooser.ExtensionFilter extFilter = new FileChooser.ExtensionFilter("PNG files", "*.PNG"); saveFile.getExtensionFilters().add(extFilter); File imageFile = saveFile.showSaveDialog(mainStage); ImageIO.write(bImage, ".png", imageFile); InputStream is = new FileInputStream(imageFile); byte[] bytes = IOUtils.toByteArray(is); int pictureId = workBook.addPicture(bytes, Workbook.PICTURE_TYPE_PNG); is.close(); CreationHelper helper = workBook.getCreationHelper(); Drawing drawing = sheet.createDrawingPatriarch(); ClientAnchor anchor = helper.createClientAnchor(); anchor.setCol1(1); anchor.setRow1(2); Picture pict = drawing.createPicture(anchor, pictureId); FileOutputStream fos = new FileOutputStream(filePath); workBook.write(fos); fis.close(); fos.close(); workBook.close(); } }
my FXML
<VBox prefHeight="400.0" prefWidth="640.0" xmlns="http://javafx.com/javafx/17" xmlns:fx="http://javafx.com/fxml/1" fx:controller="Main"> <children> <MenuBar prefHeight="67.0" prefWidth="640.0" style="-fx-background-color: white;" VBox.vgrow="NEVER" /> <AnchorPane maxHeight="-1.0" maxWidth="-1.0" prefHeight="-1.0" prefWidth="-1.0" style="-fx-background-color: #00A5AD;" VBox.vgrow="ALWAYS"> <children> <TabPane layoutY="-1.0" prefHeight="375.0" prefWidth="640.0" style="-fx-background-color: white;" tabClosingPolicy="UNAVAILABLE"> <tabs> <Tab text="Tooling layout"> <content> <AnchorPane fx:id="layoutPane" minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0"> <children> <Label layoutX="16.0" layoutY="115.0" text="Selected component Image:" /> <Button layoutX="4.0" layoutY="26.0" mnemonicParsing="false" onAction="#handleImage" style="-fx-background-color: black;" text="Upload Image of Component" textFill="WHITE" /> <Rectangle arcHeight="5.0" arcWidth="5.0" fill="WHITE" height="319.0" layoutX="207.0" layoutY="17.0" scaleZ="0.0" stroke="BLACK" strokeType="INSIDE" width="426.0" /> <Button layoutX="3.0" layoutY="72.0" mnemonicParsing="false" onAction="#exportImage" style="-fx-background-color: black;" text="Export Layout to SpreadSheet" textFill="WHITE" /> <StackPane fx:id="stackPane" layoutX="217.0" layoutY="26.0" prefHeight="301.0" prefWidth="409.0" /> </children> </AnchorPane> </content> </Tab> </tabs> </TabPane> </children> </AnchorPane> </children> </VBox>
my App class:
import javafx.application.Application; import javafx.fxml.FXMLLoader; import javafx.scene.Parent; import javafx.scene.Scene; import javafx.stage.Stage; public class App extends Application{ public void start(Stage primaryStage) throws Exception { try{ FXMLLoader loader = new FXMLLoader(getClass().getResource("mainframe.fxml")); Parent root = (Parent) loader.load(); Scene scene = new Scene(root); primaryStage.setTitle("Excel Populator"); primaryStage.setScene(scene); primaryStage.show(); } catch (Exception e){ e.printStackTrace(); } } public static void main(String[] args) throws Exception { launch(args); } }
Advertisement
Answer
So I actually was able to get my code working by removing a few things and realizing that I was never actually creating a file that ImageIO would write to in essence I was able to do all the Buffered Image code and FXutils code in a single line and create a new file each time the snapshot was to be saved so that ImageIO could write my taken snapshot to that Png file.
Those were my mistakes below is what I changed:
Image finalImage = stackPane.snapshot(null, null); FileChooser saveFile = new FileChooser(); FileChooser.ExtensionFilter extFilter = new FileChooser.ExtensionFilter("PNG files", "*.PNG"); saveFile.getExtensionFilters().add(extFilter); File imageFile = saveFile.showSaveDialog(mainStage); ImageIO.write(SwingFXUtils.fromFXImage(finalImage, null), "png", imageFile);