Created
January 17, 2020 18:16
-
-
Save tresf/94c11d6079dda2cc893314f40747fc9a to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import javafx.application.Application; | |
import javafx.application.Platform; | |
import javafx.beans.value.ChangeListener; | |
import javafx.beans.value.ObservableValue; | |
import javafx.concurrent.Worker; | |
import javafx.embed.swing.SwingFXUtils; | |
import javafx.scene.Scene; | |
import javafx.scene.SnapshotParameters; | |
import javafx.scene.image.WritableImage; | |
import javafx.scene.web.WebView; | |
import javafx.stage.Stage; | |
import java.awt.image.BufferedImage; | |
import java.io.IOException; | |
import java.util.concurrent.atomic.AtomicBoolean; | |
import java.util.concurrent.atomic.AtomicReference; | |
import java.util.logging.Logger; | |
public class WebViewResize extends Application { | |
private static WebViewResize instance = null; | |
private static AtomicBoolean started = new AtomicBoolean(false); | |
private static AtomicBoolean finished = new AtomicBoolean(true); | |
private static AtomicReference<Throwable> thrown = new AtomicReference<>(null); | |
private static AtomicReference<BufferedImage> capture = new AtomicReference<>(null); | |
// our main objects | |
private static WebView webView = null; | |
private static Stage stage = null; | |
private static final int STARTUP_TIMEOUT= 10; // seconds | |
private static final int STARTUP_SLEEP_INTERVAL = 250; // millis | |
private static final int CAPTURE_SLEEP_INTERVAL = 10; // millis | |
private static final Logger log = Logger.getLogger(WebViewResize.class.getName()); | |
/** Called by JavaFX thread */ | |
public WebViewResize() { | |
instance = this; | |
} | |
/** Starts JavaFX thread if not already running */ | |
public static synchronized void initialize() throws IOException { | |
if (instance == null) { | |
new Thread() { | |
public void run() { | |
Application.launch(WebViewResize.class); | |
} | |
}.start(); | |
} | |
for(int i = 0; i < (STARTUP_TIMEOUT * 1000); i += STARTUP_SLEEP_INTERVAL) { | |
if (started.get()) { break; } | |
log.fine("Waiting for JavaFX..."); | |
try { Thread.sleep(STARTUP_SLEEP_INTERVAL); } catch(Exception ignore) {} | |
} | |
if (!started.get()) { | |
throw new IOException("JavaFX did not start"); | |
} | |
} | |
@Override | |
public void start(Stage primaryStage) throws Exception { | |
started.set(true); | |
log.fine("Started JavaFX, creating WebView..."); | |
stage = primaryStage; | |
primaryStage.setScene(new Scene(webView = new WebView())); | |
Worker<Void> worker = webView.getEngine().getLoadWorker(); | |
worker.stateProperty().addListener(stateListener); | |
//prevents JavaFX from shutting down when hiding window | |
Platform.setImplicitExit(false); | |
} | |
/** Listens for a SUCCEEDED state to activate image capture **/ | |
private static ChangeListener<Worker.State> stateListener = new ChangeListener<Worker.State>() { | |
@Override | |
public void changed(ObservableValue<? extends Worker.State> ov, Worker.State oldState, Worker.State newState) { | |
if (newState == Worker.State.SUCCEEDED) { | |
// start image capture | |
WritableImage snapshot = webView.snapshot(new SnapshotParameters(), null); | |
capture.set(SwingFXUtils.fromFXImage(snapshot, null)); | |
finished.set(true); | |
stage.hide(); | |
} | |
} | |
}; | |
/** Loads the specified HTML, waits for all events, returns a snapshot **/ | |
public static synchronized BufferedImage capture(final String html) throws Throwable { | |
capture.set(null); | |
thrown.set(null); | |
finished.set(false); | |
// run these actions on the JavaFX thread | |
Platform.runLater(new Thread() { | |
public void run() { | |
try { | |
webView.getEngine().loadContent(html, "text/html"); | |
stage.show(); // will not capture without showing stage | |
stage.toBack(); | |
} | |
catch(Throwable t) { | |
thrown.set(t); | |
} | |
} | |
}); | |
// wait for capture to complete by monitoring finished state | |
while(!finished.get() && thrown.get() == null) { | |
log.fine("Waiting on capture..."); | |
try { | |
Thread.sleep(CAPTURE_SLEEP_INTERVAL); | |
} | |
catch(InterruptedException e) { | |
log.warning(e.getLocalizedMessage()); | |
} | |
} | |
if (thrown.get() != null) { | |
throw thrown.get(); | |
} | |
return capture.get(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment