[英]How do I make the background of a WebView transparent?
我在 IntelliJ IDEA 中有一個 Maven 項目,使用 JDK 15 和 JavaFX 15。
我試過了:
什么都沒有成功。 如何使WebView的背景透明?
我的模塊信息.java:
module project {
requires javafx.controls;
requires javafx.web;
requires javafx.graphics;
requires uk.co.caprica.vlcj;
requires uk.co.caprica.vlcj.javafx;
exports project;
}
我的 pom.xml 依賴項:
<dependencies>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-controls</artifactId>
<version>15</version>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-web</artifactId>
<version>15</version>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-graphics</artifactId>
<version>15</version>
</dependency>
<dependency>
<groupId>uk.co.caprica</groupId>
<artifactId>vlcj</artifactId>
<version>4.7.0</version>
</dependency>
<dependency>
<groupId>uk.co.caprica</groupId>
<artifactId>vlcj-javafx</artifactId>
<version>1.0.2</version>
</dependency>
</dependencies>
我創建了一個新項目並嘗試從答案中實現示例。 發生了。 不幸的是,單擊按鈕后背景顏色不會變得透明。 你知道為什么這個例子不起作用嗎?
主要.java:
import javafx.application.Application;
import javafx.stage.Stage;
import com.sun.webkit.dom.HTMLDocumentImpl;
import java.lang.reflect.Field;
import javafx.geometry.Insets;
import javafx.scene.control.Button;
import javafx.scene.layout.Background;
import javafx.scene.layout.BackgroundFill;
import javafx.scene.layout.CornerRadii;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.web.WebView;
public class Main extends Application {
@Override
public void start(final Stage stage) {
initStage(stage);
}
private void initStage(Stage stage){
WebView wv = new WebView();
wv.setStyle("-fx-background-color: transparent;");
wv.getEngine().load("https://w3schools.com");
VBox vb = new VBox(wv);
vb.setBackground(new Background(new BackgroundFill(Color.ORANGERED, CornerRadii.EMPTY, Insets.EMPTY)));
Button b = new Button("remove page background");
b.setOnAction((event) -> {
HTMLDocumentImpl cast = (HTMLDocumentImpl) wv.getEngine().getDocument();
try {
Field f = wv.getEngine().getClass().getDeclaredField("page");
f.setAccessible(true);
com.sun.webkit.WebPage page = (com.sun.webkit.WebPage) f.get(wv.getEngine());
page.setBackgroundColor((new java.awt.Color(1, 1, 1, 1)).getRGB());
f.setAccessible(false);
} catch (Exception e) {
}
});
vb.getChildren().add(b);
stage.setScene(new Scene(vb));
stage.show();
}
public static void main(String[] args) {
launch();
}
}
虛擬機選項:
--module-path ${PATH_TO_FX} --add-modules javafx.controls,javafx.web --add-exports javafx.web/com.sun.webkit.dom=ALL-UNNAMED
WebView 在 web 頁面中呈現 DOM CSS。 如果你想要一個透明的背景,你也必須在那里修改 CSS。
編輯...以下工作,但打開了一罐蠕蟲。
@Override
public void start(Stage primaryStage) throws Exception {
WebView wv = new WebView();
wv.setStyle("-fx-background-color: transparent;");
wv.getEngine().load("https://w3schools.com");
VBox vb = new VBox(wv);
vb.setBackground(new Background(new BackgroundFill(Color.ORANGERED, CornerRadii.EMPTY, Insets.EMPTY)));
Button b = new Button("remove page background");
b.setOnAction((event) -> {
HTMLDocumentImpl cast = HTMLDocumentImpl.class.cast(wv.getEngine().getDocument());
Node item = cast.getElementsByTagName("html").item(0);
try {
// Use reflection to retrieve the WebEngine's private 'page' field.
Field f = wv.getEngine().getClass().getDeclaredField("page");
f.setAccessible(true);
com.sun.webkit.WebPage page = (com.sun.webkit.WebPage) f.get(wv.getEngine());
page.setBackgroundColor((new java.awt.Color(0, 0, 0, 0)).getRGB());
f.setAccessible(false);
} catch (Exception e) {
}
});
vb.getChildren().add(b);
primaryStage.setScene(new Scene(vb));
primaryStage.show();
}
添加了導入列表
import com.sun.webkit.dom.HTMLDocumentImpl;
import java.lang.reflect.Field;
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.Background;
import javafx.scene.layout.BackgroundFill;
import javafx.scene.layout.CornerRadii;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.web.WebView;
import javafx.stage.Stage;
import org.w3c.dom.Node;
您可能需要添加以下內容:
--add-exports=javafx.web/com.sun.webkit.dom=ALL-UNNAMED \
在project.properties
文件的run.jvm
args 參數中。
注意......這是一種黑客行為,oracle 不鼓勵這樣做。
編輯 (2)
同樣,這是一種 hack,充其量是不完整的。
此快照是在移除背景后立即向下滾動后拍攝的。
從技術上講,我認為正在發生的事情是,每當 DOM 渲染引擎重繪一個框架時,它都應該分層繪制所有內容,而背景永遠不會是透明的。 因此,它不會“清除”東西,它只是反復在自身之上繪制前景。
此外,還有一件有趣的事情正在發生。
如果您 rClick + reloadpage,或者如果您單擊“接受 cookie”,頁面背景將被刪除......我很確定這會觸發 dom 更新。
因此,顯然發生的事情是 WebView 和 WebPage 組件是兩個不同宇宙的一部分。 WebView 是 DOM 操作... WebPage 是 DOM 在處理渲染的特定階段使用的東西。
如果我對 WebPage 中的功能為何“隱藏”發表意見,我可能會暫停此帳戶......但從個人經驗來看,每當在 openJFx 中難以掌握諸如 WebPage 之類的東西時,它通常意味着您將浪費幾個月的時間來嘗試為將來很可能會更改的某些內容找到解決方案,從而使您的更改過時。
我的建議是要么放棄這個問題,要么完全改變你的心態。
我認為您應該做的基本上是在窗格之類的東西中模擬渲染。
所以...新舞台... PaneX 作為場景,解析 webview 中的任何內容,並使用 css 等將節點放在 PaneX 中,這些節點的外觀和感覺與 Z5A98E2840FD01461EDC80D7 中的內容基本相同 ...正如您可以想象的...這將是屁股上的一個窗格...
或者,您可能需要考慮獲取 openjfx 代碼庫並使用修改過的源代碼,以便通過添加額外代碼使 WebPage 有效地清除自身……但這取決於您。
最后,您必須考慮這樣做是出於可能圍繞性能問題的原因。
例如,不是只清除網頁中的背景,而是刪除頁面中 CSS 中的所有背景,您將不得不做很多事情。 這意味着性能問題,因為它本質上意味着在頁面加載時進行完整的 dom 樹解析。
經過多次嘗試,我設法達到了預期的結果。
JDK 15,JavaFX 15。
我試圖從這里實現一個例子: https://stackoverflow.com/a/26519831/10946427
並且有一個透明的背景。 然后我想通了為什么。 這是由於我通過大量試驗和錯誤添加的 VM 選項。
如果沒有這些VM 選項,該示例將無法運行:
--add-exports
javafx.web / com.sun.javafx.webkit = ALL-UNNAMED
--add-exports
javafx.web / com.sun.webkit = ALL-UNNAMED
--add-opens
javafx.web / javafx.scene.web = ALL-UNNAMED
我選擇的最好的答案示例很可能也適用於這些選項。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.