从JavaFX浏览器获取Bytebuffer

从JavaFX浏览器获取Bytebuffer,java,javafx,libgdx,webkit,chromium,Java,Javafx,Libgdx,Webkit,Chromium,我目前正在使用libgdx进行一个项目。由于我厌倦了糟糕的UI库,我想使用HTML、CSS和JS 在我的第一次尝试中,我尝试了java chromium embedded,并设法将其集成到我的项目中。通过一些思考,我能够获得浏览器的bytebuffer,并将其渲染到我的游戏顶部。问题是只有一个预编译的Win64版本,但我也想支持其他平台 由于我自己无法编译chromium,我查看了javafx浏览器。它似乎比java chromium嵌入的java代码复杂得多,因此我无法获得bytebuffer

我目前正在使用libgdx进行一个项目。由于我厌倦了糟糕的UI库,我想使用HTML、CSS和JS

在我的第一次尝试中,我尝试了java chromium embedded,并设法将其集成到我的项目中。通过一些思考,我能够获得浏览器的bytebuffer,并将其渲染到我的游戏顶部。问题是只有一个预编译的Win64版本,但我也想支持其他平台

由于我自己无法编译chromium,我查看了javafx浏览器。它似乎比java chromium嵌入的java代码复杂得多,因此我无法获得bytebuffer。 也许有人能帮我找到那辆车

我目前正在搜索:

  • com.sun.webkit.WebPage

    • 公共空白绘制(WCGraphicsContext gc、int x、int y、int w、int h)

    • 专用void paint2GC(WCGraphicsContext gc)

  • com.sun.webkit.graphics.WCRenderQueue

但是缓冲区和缓冲区列表太多了,我现在不知道“真正的”bytebuffer在哪里。

不建议使用未记录的
com.sun
API

相反,您可以使用WebView节点,并使用从中获取像素缓冲区

我不确定这是否正是你想要做的。可能还有其他方法可以实现您想要的(例如覆盖窗口而不是使用缓冲区)

下面是一个将动画WebView节点(播放视频)的快照连续拍摄到ImageView的示例

图像的顶部是原始web视图。图像的底部是覆盖帧速率的原始图像快照(当原始源WebView大小调整为全屏时,在Retina MacBook上运行时约为60fps)。可以修改示例代码中的W和H值,以检查不同图像捕获大小的性能

import javafx.animation.AnimationTimer;
import javafx.application.Application;
import javafx.concurrent.Worker;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.image.*;
import javafx.scene.layout.*;
import javafx.scene.web.WebView;
import javafx.stage.Stage;

public class VideoPlayerWithFrameByFrameSnapshot extends Application {
    private static final int W = 800;
    private static final int H = 400;

    private final long[] frameTimes = new long[100];
    private int frameTimeIndex = 0 ;
    private boolean arrayFilled = false ;

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

    @Override
    public void start(Stage stage) throws Exception {
        // create a WebView
        WebView webview = new WebView();
        webview.setMinSize(W, H);
        webview.setPrefSize(W, H);
        webview.setMaxSize(W, H);

        // create an image viewer for a WebView snapshot
        WritableImage image = new WritableImage(W, H);
        ImageView imageview = new ImageView(image);

        Label framerateLabel = new Label();

        // continuously snapshot the webview and measure current framerate.
        AnimationTimer timer = new AnimationTimer() {
            @Override
            public void handle(long now) {
                webview.snapshot(null, image);

                long oldFrameTime = frameTimes[frameTimeIndex] ;
                frameTimes[frameTimeIndex] = now ;
                frameTimeIndex = (frameTimeIndex + 1) % frameTimes.length ;
                if (frameTimeIndex == 0) {
                    arrayFilled = true ;
                }
                if (arrayFilled) {
                    long elapsedNanos = now - oldFrameTime ;
                    long elapsedNanosPerFrame = elapsedNanos / frameTimes.length ;
                    double frameRate = 1_000_000_000.0 / elapsedNanosPerFrame ;
                    framerateLabel.setText(
                        String.format(
                            "Current frame rate: %.3f", 
                            frameRate
                        )
                    );
                }
            }
        };

        // start the snapshot process once the web view load succeeds. 
        webview.getEngine().getLoadWorker().stateProperty().addListener(
            (observable, oldValue, newValue) -> {
                System.out.println(newValue);
                if (Worker.State.SUCCEEDED == newValue) {
                    timer.start();
                }
            }
        );

        // load up the big buck bunny video. 
        webview.getEngine().load(
                "http://camendesign.com/code/video_for_everybody/test.html"
        );

        // layout the scene. 
        VBox layout = new VBox(
                webview,
                new StackPane(
                        imageview,
                        framerateLabel
                )
        );
        StackPane.setAlignment(framerateLabel, Pos.TOP_LEFT);

        stage.setScene(new Scene(layout));
        stage.show();
    }
}

帧速率测量代码来自James_D的答案:


顺便说一句:如果你想用纯HTML UI制作一个游戏,那么我不明白你为什么要使用libgdx并希望访问低级绘图原语来捕获嵌入式浏览器的图形输出(而不仅仅是在用户的默认浏览器中或直接在游戏附带的嵌入式浏览器中显示HTML UI),但我想你有你追求这种方法的理由。在未来,我将尽量避免回答动机和目标不明确的问题。这不是一个坏问题,只是一个我认为帮不了多少忙的问题。

问题是,这张快照太慢了,正如我所说我的游戏需要60 fps。你怎么知道快照太慢了,你试过了吗?为什么你需要在每个游戏帧都拍摄快照?大多数web内容都是静态的,变化不大。此外,如果你通过网络加载web内容或使用大量JavaScript,大部分延迟都是由于网络加载或JavaScript pro造成的访问。您是否在试图快照并覆盖在游戏屏幕上的网页中有动画内容?页面的像素大小是多少?如果您的问题存在限制,您应该始终尝试在问题中列出这些限制。同时检查您是否使用了适当的,因为这可能会影响性能这类操作的性能。是的,快照实际上是我的第一次尝试。我将整个快照标记为bytebuffer进程,结果发现,只有方法快照使其变慢。我想用HTML制作整个游戏UI。因此,我正在将本地HTML文件加载到浏览器中。页面大小将为播放器显示器的大小。PS:我已经用java chromium嵌入了60fps,可以观看youtube视频。好的。我好像这样叫快照方法:webview.snapshot(null,null);