JavaFX WebView: игнорирование setPickOnBounds? - PullRequest
0 голосов
/ 13 апреля 2020

Я пытаюсь отобразить два прозрачных веб-представления друг над другом.

Они отображаются нормально, однако гиперссылки можно щелкнуть только для веб-просмотра вверху.

Мой понимание состоит в том, что, установив setPickOnBounds(false), клики по прозрачным пикселям верхнего WebView должны go до нижнего 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) {}
            }
        }
    }
}

1 Ответ

0 голосов
/ 13 апреля 2020

Я еще не нашел элегантного решения, но это работает.

Во-первых, события мыши, полученные фронтом WebView webViewFront, должны быть перенаправлены на webViewBack:

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

Это позволит кликам, перетаскиваниям и т. Д. c работать с обоими кадрами.

Что касается использования правильного курсора, то это немного сложно. Отображается только курсор спереди WebView. Поэтому нашему веб-представлению back должно быть разрешено изменять передний курсор:

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 с гиперссылками, работающими для обоих.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...