Skip to content
Advertisement

No png File created after creating snapshot of parent node and saving through FileChooser.showSaveDialog() Java

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);
User contributions licensed under: CC BY-SA
4 People found this is helpful
Advertisement