2011-10-17 12 views
10

Szukam sposobu na załadowanie strony i zapisanie renderowania jako obrazu tak, jak zrobiłbyś to z CutyCapt (QT + webkit EXE, aby to zrobić)).JavaFX 2.0+ WebView/WebEngine renderuje stronę WWW do obrazu

w tej chwili i bez JavaFX, robię to poprzez wywołanie zewnętrznego procesu z java i renderowania do pliku niż ładuje ten plik do ImageBuffer ... Ani bardzo zoptymalizowane ani praktyczne, a nawet mniej wieloplatformowym ...

Korzystanie JavaFX2 + Próbowałem grać z 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; 
    } 
} 

jest przestarzała metoda: renderToImage w Scene (patrz linki poniżej), że zrobi coś bliski iz którym chciałbym być w stanie do pracy, ale jest przestarzałe ... To, że jest przestarzałe w JavaFX, wydaje się oznaczać, że nie ma javadoc reklamowania metody zastępowania i ponieważ nie mam dostępu do kodu, nie widzę, jak to się stało ...

Oto kilka stron gdzie znalazłem pewne informacje, ale nic do renderowania strony internetowej do obrazu:

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

canvasImage i saveImage(canvasImage, fc.getSelectedFile()) z tego jednego:

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

innymi:

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/ 

Odpowiedz

8

Zrobiłem to, uruchamiając JavaFX WebView na Swing JFrame i JFXPanel. A następnie używam metody paint() w JFXPanel, gdy status WebEngine jest ZWOLNIONY.

Możesz śledzić ten tutorial dokonać WebView:

Poniższy kod pokazuje jak przechwycić renderowany ekran przed 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

Użyłbym 'print' lub' printAll' ponad 'paint', ale podstawową ideą jest WAY cool! – MadProgrammer

+0

Co to jest FXBrowser? – Pablo

2

Obejście opublikowane przez inżynierów JavaFX: Snapshot does not work with (invisible) WebView nodes.

Kiedy biorąc migawkę sceny, która zawiera węzeł WebView, odczekać co najmniej 2 klatek przed wydaniem komendy snapshot. Można to zrobić za pomocą licznika w AnimationTimer, aby pominąć 2 impulsy i wykonać migawkę na trzecim impulsie.

Gdy masz swoją migawkę można przekonwertować obraz do AWT BufferedImage i kodować obrazu do formatu jak PNG lub JPG, używając ImageIO.

+2

nowy link do problemu: https://bugs.openjdk.java.net/browse/JDK-8087569 –

7

Dla użytkowników JavaFX 2.2 istnieje o wiele bardziej czyste i eleganckie rozwiązanie oparte na migawce węzła JavaFX.Można spojrzeć do dokumentacji węzła JavaFX w:

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

Oto przykład biorąc przechwytywanie z WebView Node (jak 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); 
    } 

miałem żadnych problemów z tego rozwiązania , a widok WWW jest perfekcyjnie renderowany w PNG zgodnie z rozmiarem węzła. Każdy węzeł JavaFx może być renderowany i zapisywany do pliku za pomocą tej metody.

Mam nadzieję, że ta pomoc!

+0

Ale co z zrzuty ekranu bez głowy? więc mógłbym uruchomić go po stronie serwera, aby robić zrzuty ekranu, takie jak z PhantomJS – ses

+0

Niestety, ale nie rozumiem cię –

+1

Po prostu szukam działającego przykładu, który mógłby wykonać migawkę z NO pokazującym jakąkolwiek formę/ramkę - "bez głowy". Podobnie jak przy uruchamianiu aplikacji, wykonuje migawkę dowolnego html, bez pokazywania jakichkolwiek okien na ekranie. Podobnie jak PhantomJS. – ses