This example is taken from learn JavaFx Kihori Shara
code:

package javafxtemplate1;
//
//textProperty().addListener Listview Label
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javafx.application.Application;
import javafx.embed.swing.SwingFXUtils;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.image.WritableImage;
import javafx.scene.layout.GridPane;;
import javafx.scene.SnapshotResult;
import javafx.scene.image.Image;
import javafx.util.Callback;
import javafx.stage.Stage;
import javafx.stage.FileChooser;
import javafx.stage.FileChooser.ExtensionFilter;
import javax.imageio.ImageIO;

/**
*
* @author Manas9
*/
public class JavaFXTemplate1 extends Application {

@Override
public void start(Stage primaryStage) throws Exception {
//
GridPane root = new GridPane();
Scene scene = new Scene(root);

Label nameLbl = new Label("Name:");
TextField nameField = new TextField("Prema");

Button syncSnapshotBtn = new Button("Synchronous Snapshot");
syncSnapshotBtn.setOnAction(e -> syncSnapshot(scene));

Button asyncSnapshotBtn = new Button("Asynchronous Snapshot");
asyncSnapshotBtn.setOnAction(e -> asyncSnapshot(scene));

root.setHgap(10);
root.addRow(0, nameLbl, nameField, syncSnapshotBtn);
root.add(asyncSnapshotBtn, 2, 1);

primaryStage.setScene(scene);
primaryStage.setTitle("Taking a Snapshot of a Scene");
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
private void syncSnapshot(Scene scene) {
WritableImage image = scene.snapshot(null);
ImageUtil.saveToFile(image);
}

private void asyncSnapshot(Scene scene) {
// Create a Callback. Its call() method is called when
// the snapshot is ready. The getImage() method returns the snapshot
Callback<SnapshotResult, Void> callback = (SnapshotResult result) -> {
WritableImage image = result.getImage();
ImageUtil.saveToFile(image);
return null;
};

scene.snapshot(callback, null);
}

private static class ImageUtil {

public ImageUtil() {
}
public static void saveToFile(Image image) {
// Ask the user for the file name
FileChooser fileChooser = new FileChooser();
fileChooser.setTitle("Select an image file name");
fileChooser.setInitialFileName("untitled");
ExtensionFilter pngExt = new ExtensionFilter("PNG Files", "*.png");
ExtensionFilter jpgExt = new ExtensionFilter("JPEG Files", "*.jpg", "*.jpeg");
fileChooser.getExtensionFilters().addAll(pngExt, jpgExt);

File outputFile = fileChooser.showSaveDialog(null);
if (outputFile == null) {
return;
}

ExtensionFilter selectedExt = fileChooser.getSelectedExtensionFilter();
String imageFormat = "png";
if (selectedExt == jpgExt) {
imageFormat = "jpg";
}

// Check for the file extension. Add oen, iff not specified
String fileName = outputFile.getName().toLowerCase();
switch (imageFormat) {
case "jpg":
if (!fileName.endsWith(".jpeg") && !fileName.endsWith(".jpg")) {
outputFile = new File(outputFile.getParentFile(),
outputFile.getName() + ".jpg");
}
break;
case "png":
if (!fileName.endsWith(".png")) {
outputFile = new File(outputFile.getParentFile(),
outputFile.getName() + ".png");
}
}

// Convert the image to a buffered image
BufferedImage bImage = SwingFXUtils.fromFXImage(image, null);

// Save the image to the file
try {
ImageIO.write(bImage, imageFormat, outputFile);
}
catch (IOException e) {
throw new RuntimeException(e);
}
}
}
}