2011-10-17 20 views
10

Estoy buscando una forma de cargar una página y guardar el renderizado como una imagen como lo haría con CutyCapt (QT + webkit EXE para hacer eso)JavaFX 2.0+ WebView/WebEngine rinde página web a una imagen

Por el momento, y sin JavaFX, lo hago llamando a un proceso externo de Java y de la representación a presentar de cargar ese archivo en un ImageBuffer ... Ni muy optimizado ni práctico e incluso plataforma cruzada de menos ...

Usando JavaFX2 + I intentado jugar con la vista Web & 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; 
    } 
} 

hay un método en desuso: renderToImage en Scene (ver enlaces más abajo) que hacer algo que se acerca y con el que me podría ser capaz para trabajar, pero está en desuso ... Ser desaprobado en JavaFX parece significar que no hay ningún anuncio javadoc el método de reemplazo y porque no tengo acceso al código, no puedo ver cómo se hizo ...

Aquí hay un par de sitios donde me encontré con algo de información, pero nada para hacer una página web a una imagen:

http://tornorbye.blogspot.com/2010/02/how-to-render-javafx-node-into-image.html 

canvasImage y saveImage(canvasImage, fc.getSelectedFile()) de éste:

http://javafx.com/samples/EffectsPlayground/src/Main.fx.html 

Otros:

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/ 

Respuesta

8

Lo he hecho mediante el lanzamiento de JavaFX WebView en un JFrame Swing y JFXPanel. Y luego uso el método paint() en JFXPanel una vez que el estado de WebEngine es EXITOSO.

Usted puede seguir este tutorial para hacer un WebView:

El código siguientes muestran cómo capturo la pantalla representan a partir de 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(); 
} 
+0

Usaría 'print' o' printAll' sobre 'paint', pero la idea básica es WAY cool! – MadProgrammer

+0

¿Qué es FXBrowser? – Pablo

2

Solución del problema publicada por los ingenieros de JavaFX: Snapshot does not work with (invisible) WebView nodes.

Al tomar una instantánea de una escena que contiene un nodo WebView, espere por lo menos 2 marcos antes de emitir el comando snapshot. Esto se puede hacer utilizando un contador en AnimationTimer para omitir 2 pulsos y tomar la instantánea en el 3er pulso.

Una vez que tenga la instantánea, puede convertir la imagen a un AWT BufferedImage y codificar la imagen para dar formato, como png o jpg, utilizando ImageIO.

+2

el nuevo enlace al problema: https://bugs.openjdk.java.net/browse/JDK-8087569 –

7

Para los usuarios de JavaFX 2.2 hay una solución mucho más limpia y elegante basada en la instantánea de JavaFX Node.Puede echar un vistazo a la documentación nodo de JavaFX en:

http://docs.oracle.com/javafx/2/api/javafx/scene/Node.html

Aquí es un ejemplo de tomar una captura de un nodo del WebView (como web View)

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); 
    } 

No he tenido problemas con esta solución , y la vista web se representa perfectamente en PNG de acuerdo con el tamaño del nodo. Cualquier nodo JavaFx se puede representar y guardar en un archivo con este método.

¡Espero que esta ayuda!

+0

Pero, ¿qué pasa con la captura de pantallas sin cabeza? así que podría lanzarlo en el lado del servidor para tomar capturas de pantalla como con PhantomJS – ses

+0

Lo siento, pero no te entiendo –

+1

Solo busco un ejemplo de trabajo que podría tomar una instantánea sin mostrar ningún formulario/marco - "sin cabeza". Al igual que el lanzamiento de la aplicación, toma una instantánea de cualquier html que paso sin mostrar ninguna ventana en la pantalla. Como PhantomJS lo hace. – ses

Cuestiones relacionadas