首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >尝试将javafx WebView呈现到屏幕外缓冲区或FBO

尝试将javafx WebView呈现到屏幕外缓冲区或FBO
EN

Stack Overflow用户
提问于 2016-11-16 21:21:39
回答 1查看 917关注 0票数 2

最终目标是能够以30 for或更高的速度记录WebView的输出,也许可以为javafx设置一个FBO?然后,我可以在任何我想要的框架中拉出框架。

我在UploadingPainter上偶然发现了一些人,这让我觉得这是可能的。奋斗的是,这似乎是在引擎盖之下,对我来说有点新。

有人知道怎么做这样的事吗?

这是我在调试过程中遇到的代码:

代码语言:javascript
复制
@Override
public void setStage(GlassStage stage) {
    super.setStage(stage);
    if (stage != null) {
        WindowStage wstage  = (WindowStage)stage;
        if (wstage.needsUpdateWindow() || GraphicsPipeline.getPipeline().isUploading()) {
            if (Pixels.getNativeFormat() != Pixels.Format.BYTE_BGRA_PRE ||
                ByteOrder.nativeOrder() != ByteOrder.LITTLE_ENDIAN) {
                throw new UnsupportedOperationException(UNSUPPORTED_FORMAT);
            }
            painter = new UploadingPainter(this);
        } else {
            painter = new PresentingPainter(this);
        }
        painter.setRoot(getRoot());
        paintRenderJob = new PaintRenderJob(this, PaintCollector.getInstance().getRendered(), painter);
    }
}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-11-17 02:04:44

下面是一个在WebView中捕获动画的示例。

从web视图中捕获的图像被放置在分页器中,以便查看它们,这样就可以很容易地查看它们。如果您愿意,可以使用SwingFXUtilsImageIO将它们写成文件。如果要将生成的图像放入缓冲区,可以使用它们的PixelReader

它不太像我希望的那样起作用。我想对WebView进行快照,而不把它放在可见的阶段。对于JavaFX中的其他节点类型(据我所知),对没有处于某个阶段的节点进行快照可以正常工作(据我所知),但是由于一些奇怪的原因,它不适用于WebView。因此,示例实际上在显示窗口后面创建了一个新的阶段,该窗口为动画捕获结果显示图像序列。我知道这并不完全是你想要的,但这就是你想要的。

代码语言:javascript
复制
import javafx.animation.AnimationTimer;
import javafx.application.Application;
import javafx.beans.property.*;
import javafx.collections.*;
import javafx.concurrent.Worker;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.SnapshotParameters;
import javafx.scene.control.*;
import javafx.scene.image.*;
import javafx.scene.layout.*;
import javafx.scene.web.WebView;
import javafx.stage.Stage;

public class WebViewAnimationCaptor extends Application {

    private static final String CAPTURE_URL =
            "https://upload.wikimedia.org/wikipedia/commons/d/dd/Muybridge_race_horse_animated.gif";

    private static final int N_CAPS_PER_SECOND = 10;
    private static final int MAX_CAPTURES = N_CAPS_PER_SECOND * 5;
    private static final int W = 186, H = 124;

    class CaptureResult {
        ObservableList<Image> images = FXCollections.observableArrayList();
        DoubleProperty progress = new SimpleDoubleProperty();
    }

    @Override public void start(Stage stage) {
        CaptureResult captures = captureAnimation(CAPTURE_URL);
        Pane captureViewer = createCaptureViewer(captures);

        stage.setScene(new Scene(captureViewer, W + 40, H + 80));
        stage.show();
    }

    private StackPane createCaptureViewer(CaptureResult captures) {
        ProgressIndicator progressIndicator = new ProgressIndicator();
        progressIndicator.progressProperty().bind(captures.progress);
        progressIndicator.setPrefSize(W, H);

        StackPane stackPane = new StackPane(progressIndicator);
        stackPane.setPadding(new Insets(10));
        if (captures.progress.get() >= 1.0) {
            stackPane.getChildren().setAll(
                createImagePages(captures.images)
            );
        } else {
            captures.progress.addListener((observable, oldValue, newValue) -> {
                if (newValue.doubleValue() >= 1.0) {
                    stackPane.getChildren().setAll(
                            createImagePages(captures.images)
                    );
                }
            });
        }

        return stackPane;
    }

    private Pagination createImagePages(ObservableList<Image> captures) {
        Pagination pagination = new Pagination();
        pagination.setPageFactory(param -> {
            ImageView currentImage = new ImageView();
            currentImage.setImage(
                    param < captures.size()
                            ? captures.get(param)
                            : null
            );

            StackPane pageContent = new StackPane(currentImage);
            pageContent.setPrefSize(W, H);

            return pageContent;
        });

        pagination.setCurrentPageIndex(0);
        pagination.setPageCount(captures.size());
        pagination.setMaxPageIndicatorCount(captures.size());

        return pagination;
    }

    private CaptureResult captureAnimation(final String url) {
        CaptureResult captureResult = new CaptureResult();

        WebView webView = new WebView();
        webView.getEngine().load(url);
        webView.setPrefSize(W, H);

        Stage captureStage = new Stage();
        captureStage.setScene(new Scene(webView, W, H));
        captureStage.show();

        SnapshotParameters snapshotParameters = new SnapshotParameters();
        captureResult.progress.set(0);

        AnimationTimer timer = new AnimationTimer() {
            long last = 0;

            @Override
            public void handle(long now) {
                if (now > last + 1_000_000_000.0 / N_CAPS_PER_SECOND) {
                    last = now;
                    captureResult.images.add(webView.snapshot(snapshotParameters, null));
                    captureResult.progress.setValue(
                            captureResult.images.size() * 1.0 / MAX_CAPTURES
                    );
                }

                if (captureResult.images.size() > MAX_CAPTURES) {
                    captureStage.hide();
                    this.stop();
                }
            }
        };

        webView.getEngine().getLoadWorker().stateProperty().addListener((observable, oldValue, newValue) -> {
            if (Worker.State.SUCCEEDED.equals(newValue)) {
                timer.start();
            }
        });

        return captureResult;
    }

    public static void main(String[] args) { launch(args); }
}

要微调动画序列捕获,您可以查看这个关于AnimationTimers在JavaFX中的信息

如果您需要使这个东西“无头”,这样就不需要一个可见的阶段,您可以尝试这个执行"Java图像捕获,HTML快照,HTML到图像“的danialfarid的要点 (尽管我没有编写链接的gist,也没有尝试过)。

无头是关键,在我的情况下。问题中的(linux)机器运行在服务器场中,完全无头。至于要点,我在里面看到了一个节目,但我会仔细看一看,以确保我没有忽略一些东西。

该要点基于用于JavaFX系统的单片玻璃渲染工具包。该工具包支持任何系统上基于软件的无头渲染。

来自单片文件

无头端口什么也不做。它适用于当您想要运行没有图形、输入或平台依赖关系的JavaFX时。渲染仍然会发生,只是没有出现在屏幕上。

无头端口使用LinuxInputDeviceRegistry实现的InputDeviceRegistry。但是,无头端口根本不访问任何实际的Linux设备或任何本机API;它在设备模拟模式中使用Linux输入注册表。这允许即使在非Linux平台上也可以模拟Linux设备输入。tests/system/src/test/java/com/sun/glass/ui/monocle/input中的测试广泛地使用了这个特性。

如果基于JavaFX的方法最终不适合您,您可以考虑另一个(而不是与JavaFX相关的)无头HTML呈现工具包,例如PhantomJS

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/40642573

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档