#java #image #save #render #javafx
#java #изображение #Сохранить #визуализация #javafx
Вопрос:
Я ищу способ загрузить страницу и сохранить рендеринг в виде изображения так же, как вы бы сделали с CutyCapt (QT webkit EXE для этого).
На данный момент и без JavaFX я делаю это, вызывая внешний процесс из java и отображая его в файл, а не загружая этот файл в буфер изображений… Не очень оптимизирован, не практичен и даже менее кроссплатформенен…
Используя JavaFX2 , я попытался поиграть с WebView и WebEngine:
public class WebComponentTrial extends Application {
private Scene scene;
@Override
public void start(final Stage primaryStage) throws Exception {
primaryStage.setTitle("Web View");
final Browser browser = new Browser();
scene = new Scene(browser, 1180, 800, Color.web("#666970"));
primaryStage.setScene(scene);
scene.getStylesheets().add("webviewsample/BrowserToolbar.css");
primaryStage.show();
}
public static void main(final String[] args) {
launch(args);
}
}
class Browser extends Region {
static { // use system proxy settings when standalone application
// System.setProperty("java.net.useSystemProxies", "true");
}
final WebView browser = new WebView();
final WebEngine webEngine = browser.getEngine();
public Browser() {
getStyleClass().add("browser");
webEngine.load("http://www.google.com/");
getChildren().add(browser);
}
@Override
protected void layoutChildren() {
final double w = getWidth();
final double h = getHeight();
layoutInArea(browser, 0, 0, w, h, 0, HPos.CENTER, VPos.CENTER);
}
@Override
protected double computePrefWidth(final double height) {
return 800;
}
@Override
protected double computePrefHeight(final double width) {
return 600;
}
}
Существует устаревший метод: renderToImage
in Scene
(см. Ссылки Ниже), который будет делать что-то близкое и с которым я мог бы работать, но он устарел…
То, что в JavaFX он устарел, по-видимому, означает, что javadoc не рекламирует метод замены, и поскольку у меня нет доступа к коду, я не вижу, как это было сделано…
Вот несколько сайтов, на которых я нашел некоторую информацию, но ничего, чтобы отобразить веб-страницу в изображение:
http://tornorbye.blogspot.com/2010/02/how-to-render-javafx-node-into-image.html
canvasImage
и saveImage(canvasImage, fc.getSelectedFile())
из этого :
http://javafx.com/samples/EffectsPlayground/src/Main.fx.html
Прочее:
http://download.oracle.com/javafx/2.0/webview/jfxpub-webview.htm
http://download.oracle.com/javafx/2.0/get_started/jfxpub-get_started.htm
http://fxexperience.com/2011/05/maps-in-javafx-2-0/
Ответ №1:
Я сделал это, запустив JavaFX WebView на Swing JFrame и JFXPanel. А затем я использую метод paint () в JFXPanel, как только статус WebEngine будет ВЫПОЛНЕН УСПЕШНО.
Вы можете следовать этому руководству, чтобы создать WebView: интеграция JavaFX в приложения Swing
Приведенный ниже код демонстрирует, как я захватываю отображаемый экран из JFXPanel.
public static void main(String args[]) {
jFrame = new JFrame("Demo Browser");
jfxPanel = new JFXPanel();
jFrame.add(jfxPanel);
jFrame.setVisible(true);
jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
Platform.runLater(new Runnable() {
@Override
public void run() {
browser = new FXBrowser();
jfxPanel.setScene(browser.getScene());
jFrame.setSize((int) browser.getWebView().getWidth(), (int) browser.getWebView().getHeight());
browser.getWebEngine().getLoadWorker().stateProperty().addListener(
new ChangeListener() {
@Override
public void changed(ObservableValue observable,
Object oldValue, Object newValue) {
State oldState = (State) oldValue;
State newState = (State) newValue;
if (State.SUCCEEDED == newValue) {
captureView();
}
}
});
}
});
}
});
}
private static void captureView() {
BufferedImage bi = new BufferedImage(jfxPanel.getWidth(), jfxPanel.getHeight(), BufferedImage.TYPE_INT_ARGB);
Graphics graphics = bi.createGraphics();
jfxPanel.paint(graphics);
try {
ImageIO.write(bi, "PNG", new File("demo.png"));
} catch (IOException e) {
e.printStackTrace();
}
graphics.dispose();
bi.flush();
}
Комментарии:
1. Я бы использовал
printAll
overpaint
, но основная идея — это круто!2. Что такое FXBrowser?
Ответ №2:
Для пользователей JavaFX 2.2 существует гораздо более чистое и элегантное решение, основанное на моментальном снимке узла JavaFX. Вы можете ознакомиться с документацией узла JavaFX по адресу:
http://docs.oracle.com/javafx/2/api/javafx/scene/Node.html
Вот пример получения записи с узла WebView (как WebView)
File destFile = new File("test.png");
WritableImage snapshot = webView.snapshot(new SnapshotParameters(), null);
RenderedImage renderedImage = SwingFXUtils.fromFXImage(snapshot, null);
try {
ImageIO.write(renderedImage, "png", destFile);
} catch (IOException ex) {
Logger.getLogger(GoogleMap.class.getName()).log(Level.SEVERE, null, ex);
}
У меня не было проблем с этим решением, и webview отлично отображается в формате PNG в соответствии с размером узла. Любой узел JavaFX может быть визуализирован и сохранен в файл с помощью этого метода.
Надеюсь, это поможет!
Комментарии:
1. Но как насчет скриншотов без головы? итак, я мог бы запустить его на стороне сервера, чтобы делать скриншоты, как с PhantomJS
2. Извините, но я вас не понимаю
3. Я просто ищу рабочий пример, который мог бы сделать снимок без отображения какой-либо формы / рамки — «без головы». Как и при запуске приложения, оно делает снимок любого передаваемого мной HTML-кода, не отображая никаких окон на экране. Как это делает PhantomJS.
Ответ №3:
Обходной путь, опубликованный инженерами JavaFX: снимок не работает с (невидимым) Узлы WebView.
При создании моментального снимка сцены, содержащей узел WebView, подождите не менее 2 кадров, прежде чем выдавать команду snapshot. Это можно сделать, используя счетчик в AnimationTimer, чтобы пропустить 2 импульса и сделать снимок на 3-м импульсе.
Получив снимок, вы можете преобразовать изображение в awt BufferedImage и закодировать изображение в формат png или jpg, используя ImageIO.
Комментарии:
1. Вы когда-нибудь заставляли это работать? Я не могу заставить WebView записывать что-либо на изображение, если я на самом деле не прикреплю его к сцене и не покажу это на сцене.