2011-10-17 22 views
10

Tôi đang tìm cách tải một trang và lưu kết xuất dưới dạng hình ảnh giống như bạn làm với CutyCapt (QT + webkit EXE để thực hiện điều đó).JavaFX 2.0+ WebView/WebEngine hiển thị trang web thành hình ảnh

Tại thời điểm hiện tại và không có JavaFX, tôi làm điều đó bằng cách gọi một quá trình bên ngoài từ java và render nộp hơn tải tập tin đó vào một ImageBuffer ... Cả rất tối ưu hóa cũng không thực tế và thậm chí nền tảng ít chéo ...

Sử dụng JavaFX2 + tôi đã cố gắng chơi với 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; 
    } 
} 

có một phương pháp phản đối: renderToImage trong Scene (xem liên kết bên dưới) mà có thể làm một cái gì đó mà đến gần và với mà tôi muốn có thể có thể để làm việc nhưng nó không được chấp nhận ... Nó không được chấp nhận trong JavaFX dường như có nghĩa là không có javadoc quảng cáo phương pháp thay thế và bởi vì tôi không có quyền truy cập vào mã, tôi không thể xem nó được thực hiện như thế nào ...

Dưới đây là một vài trang web nơi tôi tìm thấy một số thông tin nhưng không có gì để làm cho một trang web để một hình ảnh:

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

canvasImagesaveImage(canvasImage, fc.getSelectedFile()) từ này:

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

khác:

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/ 

Trả lời

8

Tôi đã thực hiện việc này bằng cách khởi chạy JavaFX WebView trên Swing JFrame và JFXPanel. Và sau đó tôi sử dụng phương thức paint() trên JFXPanel khi trạng thái WebEngine được SUCCEEDED.

Bạn có thể làm theo hướng dẫn này để tạo ra một WebView:

Đoạn code dưới đây chứng minh làm thế nào tôi chụp màn hình render từ 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

Tôi muốn sử dụng 'print' hoặc' printAll' trên 'paint', nhưng ý tưởng cơ bản là WAY cool! – MadProgrammer

+0

FXBrowser là gì? – Pablo

2

Cách khắc phục do kỹ sư JavaFX đăng: Snapshot does not work with (invisible) WebView nodes.

Khi chụp một bản chụp của một cảnh có chứa một nút WebView, chờ ít nhất 2 khung trước khi ban hành lệnh snapshot. Điều này có thể được thực hiện bằng cách sử dụng bộ đếm trong một số AnimationTimer để bỏ qua 2 xung và chụp ảnh chụp ở xung thứ 3.

Một khi bạn đã nhận được bản chụp của bạn, bạn có thể chuyển đổi hình ảnh đến một AWT BufferedImage và mã hóa hình ảnh để định dạng khác như png hoặc jpg, sử dụng ImageIO.

+2

liên kết mới tới vấn đề: https://bugs.openjdk.java.net/browse/JDK-8087569 –

7

Đối với người dùng JavaFX 2.2, có một giải pháp sạch hơn và thanh lịch hơn dựa trên ảnh chụp nhanh JavaFX Node.Bạn có thể có một cái nhìn để tài liệu nút JavaFX tại địa chỉ:

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

Dưới đây là một ví dụ của việc chụp từ một WebView Node (như 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); 
    } 

Tôi không có vấn đề với giải pháp này và chế độ xem web được hiển thị hoàn hảo trong PNG theo kích thước nút. Bất kỳ nút JavaFx nào đều có thể được hiển thị và lưu vào một tệp với phương thức này.

Hy vọng trợ giúp này!

+0

Nhưng còn ảnh chụp màn hình không đầu thì sao? Vì vậy, tôi có thể khởi chạy nó ở phía máy chủ để chụp ảnh màn hình như với PhantomJS – ses

+0

Xin lỗi, nhưng tôi không hiểu bạn –

+1

Tôi chỉ tìm kiếm ví dụ làm việc có thể chụp nhanh với NO hiển thị bất kỳ biểu mẫu/khung hình nào - "không đầu". Giống như khởi chạy ứng dụng, nó sẽ chụp nhanh bất kỳ html nào tôi vượt qua mà không hiển thị bất kỳ cửa sổ nào trên màn hình. Giống như PhantomJS. – ses

Các vấn đề liên quan