【问题标题】:JavaFX WebView: ignoring setPickOnBounds?JavaFX WebView:忽略 setPickOnBounds?
【发布时间】:2020-07-25 13:18:27
【问题描述】:

我正在尝试让两个透明的 WebView 一个在另一个之上显示。

它们显示得很好,但是,超链接只能点击顶部的 WebView。

我的理解是,通过设置setPickOnBounds(false),点击顶部WebView的透明像素应该通过底部WebView。但是,它似乎确实是这样工作的,顶部的 WebView 会阻止所有点击。

有没有办法让重叠的 WebView 与超链接同时工作?

例子:

import java.lang.reflect.Field;
import javafx.application.Application;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.scene.Scene;
import javafx.scene.layout.StackPane;
import javafx.scene.web.WebEngine;
import javafx.scene.web.WebView;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
import org.w3c.dom.Document;

public class DoubleWebViews extends Application {

    @Override
    public void start(Stage primaryStage) {
        new WebPage(primaryStage);
        primaryStage.show();
    }

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

    static class WebPage{
        WebView webViewBack = new WebView();
        WebView webViewFront = new WebView();
        public WebPage(Stage mainstage){
            setupWebView(webViewBack, "<a href='https://www.google.com'>URL 1</a> can't be clicked!");
            setupWebView(webViewFront, "<br><br><br><a href='https://www.google.com'>URL 2</a>");

            StackPane root = new StackPane(webViewBack, webViewFront);
            root.setPickOnBounds(false);
            Scene scene = new Scene(root);
            mainstage.setScene(scene);
            mainstage.initStyle(StageStyle.TRANSPARENT);
        }

        void setupWebView(WebView webView, String html){
            webView.setPickOnBounds(false); // doesn't work?
            WebEngine webEngine = webView.getEngine();
            webEngine.documentProperty().addListener(new DocListener(webEngine));
            webEngine.loadContent("<body style='background : rgba(0,0,0,0);font-size: 70px;text-align:center;'>" + html + "</body>");
        }

        static class DocListener implements ChangeListener<Document>{
            private final WebEngine webEngine;
            public DocListener(WebEngine webEngine) { this.webEngine = webEngine;}
            @Override
            public void changed(ObservableValue<? extends Document> observable, Document oldValue, Document newValue) {
                try {
                    // Use reflection to retrieve the WebEngine's private 'page' field.
                    Field f = this.webEngine.getClass().getDeclaredField("page");
                    f.setAccessible(true);
                    com.sun.webkit.WebPage page = (com.sun.webkit.WebPage) f.get(this.webEngine);
                    page.setBackgroundColor((new java.awt.Color(0, 0, 0, 0)).getRGB());
                } catch (Exception ignored) {}
            }
        }
    }
}

【问题讨论】:

    标签: java javafx webview


    【解决方案1】:

    我还没有找到一个优雅的解决方案,但这很有效。

    首先,前面WebViewwebViewFront收到的鼠标事件需要转发到webViewBack

    webViewFront.addEventFilter(MouseEvent.ANY, event -> webViewBack.fireEvent(event));
    

    这将使点击、拖动等功能在两个框架上都起作用。

    至于使用正确的光标,这有点棘手。只显示前面WebView 的光标。因此,我们后面的WebView必须允许修改前面的光标:

    webViewBack.cursorProperty().addListener((obs, oldCursor, newCursor) -> webViewFront.setCursor(newCursor));
    

    现在的问题是webViewFront 在发生鼠标事件并且webViewFront 中的该位置没有超链接时会不断将其光标重置为默认值。因此,我们阻止了这种重置:

    webViewFront.cursorProperty().addListener((obs, oldCursor, newCursor) -> {
        if (newCursor != null && "DEFAULT".equals(newCursor.toString())) {
            webViewFront.setCursor(webViewBack.getCursor());
        }
    });
    

    这三个变化共同允许两个重叠的 WebView 与超链接同时工作。

    【讨论】:

      猜你喜欢
      • 2015-10-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-03-05
      • 2013-10-10
      • 2015-12-20
      • 2016-09-14
      相关资源
      最近更新 更多