【问题标题】:Whole page screenshot, Java整页截图,Java
【发布时间】:2015-11-27 17:19:32
【问题描述】:

这是我的问题 - 我有一个用 JavaFX 编写的桌面应用程序。我需要向用户显示全屏网页并将呈现的页面保存为 PNG。我需要保存整个页面(例如分辨率 1920×3500)。

现在我正在使用 Selenium 和 Firefox 来执行此操作。它工作正常,但有一个很大的缺点 - 用户必须在他的机器上安装 Firefox。

我尝试通过 JavaFX 使用 WebView 呈现网页并使用 .snapshot()。这会很棒,但这种方法并没有给我整个页面,只有 WebView 的可见部分。有什么方法可以使用 WebView 获取整个页面快照吗?或任何其他想法如何做到这一点?谢谢。

【问题讨论】:

    标签: webview javafx fullscreen snapshot webpage-screenshot


    【解决方案1】:

    您可能想查看this post。我不知道它是否有效,但它似乎是一个合理的解决方案。

    【讨论】:

    • 感谢您的回复。我已经尝试过了,但它不起作用 - 它给了我截图,例如1920×3500,但只有网站的可见部分,其余部分为黑色。我也试过这个样本gist.github.com/jewelsea/5632958。它运行良好,但如果WebView 的高度大于显示器高度,它似乎会出现问题。在这种情况下,某些网页无法正常运行 - 例如,此模板 blacktie.co/demo/pratt 的导航无法正常工作...
    【解决方案2】:

    经过大量搜索和拼凑后,我发现我在 oracle 论坛上发布的一些 SO-poster 示例的唯一问题是 webview 的大小是固定的,并且我的 css 使用在需要的 html 中(不在 JavaFX 中)。

    overflow-x: hidden;
    overflow-y: hidden;
    

    隐藏最后一个滚动条。

    所以我想出了以下快照方法(带有动画的应用程序作为您的应用程序的示例)看看它是否适用于您的尺寸,否则您可能会将javafx.scene.web.WebView.setZoom(double value) webview 缩小到可以使用的东西,您可能会丢失一些分辨率,但至少要有全貌:

    package application;
    
    import java.io.File;
    import java.io.IOException;
    
    import javax.imageio.ImageIO;
    
    import javafx.animation.Animation;
    import javafx.animation.PauseTransition;
    import javafx.animation.TranslateTransition;
    import javafx.application.Application;
    import javafx.embed.swing.SwingFXUtils;
    import javafx.event.ActionEvent;
    import javafx.event.EventHandler;
    import javafx.geometry.Insets;
    import javafx.geometry.Pos;
    import javafx.scene.Scene;
    import javafx.scene.control.Button;
    import javafx.scene.control.Label;
    import javafx.scene.effect.GaussianBlur;
    import javafx.scene.image.WritableImage;
    import javafx.scene.layout.AnchorPane;
    import javafx.scene.layout.BorderPane;
    import javafx.scene.layout.Pane;
    import javafx.scene.paint.Color;
    import javafx.scene.shape.Rectangle;
    import javafx.scene.web.WebView;
    import javafx.stage.Modality;
    import javafx.stage.Stage;
    import javafx.stage.StageStyle;
    import javafx.util.Duration;
    
    public class WebViewSnapshot extends Application {
    
        BorderPane rootPane;
        TranslateTransition animation;
    
        @Override
        public void start(Stage primaryStage) {
    
            Rectangle rect = new Rectangle(50, 50, 50, 50);
            rect.setFill(Color.CORAL);
    
            animation = createAnimation(rect);
    
            Button snapshotButton = new Button("Take snapshot");
    
            Pane pane = new Pane(rect);
            pane.setMinSize(600, 150);
    
            rootPane = new BorderPane(pane, null, null, snapshotButton, new Label("This is the main scene"));
    
            snapshotButton.setOnAction(e -> {
                // html file being shown in webview
                File htmlFile = new File ("generated/template.html");
                // the resulting snapshot png file
                File aboutFile = new File ("generated/about.png");
                generate(htmlFile, aboutFile, 1280, 720);
            });
    
            BorderPane.setAlignment(snapshotButton, Pos.CENTER);
            BorderPane.setMargin(snapshotButton, new Insets(5));
            Scene scene = new Scene(rootPane);
            primaryStage.setScene(scene);
            primaryStage.show();
        }
    
        private TranslateTransition createAnimation(Rectangle rect) {
            TranslateTransition animation = new TranslateTransition(Duration.seconds(1), rect);
            animation.setByX(400);
            animation.setCycleCount(Animation.INDEFINITE);
            animation.setAutoReverse(true);
            animation.play();
            return animation;
        }
    
        public void generate(File htmlFile, File outputFile, double width, double height) {
            animation.pause();
            // rootPane is the root of original scene in an FXML controller you get this when you assign it an id
            rootPane.setEffect(new GaussianBlur());
            Stage primaryStage = (Stage)rootPane.getScene().getWindow();
            // creating separate webview holding same html content as in original scene
            WebView webView = new WebView();
            // with the size I want the snapshot
            webView.setPrefSize(width, height);
            AnchorPane snapshotRoot = new AnchorPane(webView);
            webView.getEngine().load(htmlFile.toURI().toString());
            Stage popupStage = new Stage(StageStyle.TRANSPARENT);
            popupStage.initOwner(primaryStage);
            popupStage.initModality(Modality.APPLICATION_MODAL);
            // this popup doesn't really show anything size = 1x1, it just holds the snapshot-webview
            popupStage.setScene(new Scene(snapshotRoot, 1, 1));
            // pausing to make sure the webview/picture is completely rendered
            PauseTransition pt = new PauseTransition(Duration.seconds(2));
            pt.setOnFinished(new EventHandler<ActionEvent>() {
                @Override public void handle(ActionEvent event) {
                    WritableImage image = webView.snapshot(null, null);
                    // writing a png to outputFile
                    // writing a JPG like this will result in a pink JPG, see other posts
                    // if somebody can scrape me simple code to convert it ARGB to RGB or something
                    String format = "png";
                    try {
                        ImageIO.write(SwingFXUtils.fromFXImage(image, null), format, outputFile);
                    } catch (IOException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    } finally {
                        rootPane.setEffect(null);
                        popupStage.hide();
                        animation.play();
                    }
                }
            });
            // pausing, after pause onFinished event will take + write snapshot
            pt.play();
            // GO!
            popupStage.show();
        }
    
        public static void main(String[] args) {
            launch(args);
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2016-08-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-02-02
      • 1970-01-01
      • 2016-05-26
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多