2017-02-23 87 views
0

使用JavaFX的webview,我改變了全球所有網站DOM標籤的幾個HTML屬性(背景,邊框和顏色)。我的意圖是有一個自定義的黑暗主題,表現很像高對比度設置。我無法解決的唯一問題是代碼在最後一個方法setWebpageTheme(布爾成功)中產生的輕微延遲。它會導致明亮的白色閃爍,因爲應用了html css屬性,並將白色變爲黑色頁面背景。請參閱下面的完整代碼。JavaFX webview全球CSS黑暗主題

主類:

import javafx.application.Application; 
import javafx.scene.Parent; 
import javafx.scene.Scene; 
import javafx.stage.Stage; 

public class Main extends Application { 

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

    public Parent createContent() { 
     final WebBrowser browser = new WebBrowser(); 
     return browser; 
    } 

    @Override 
    public void start(Stage primaryStage) throws Exception { 
     primaryStage.setResizable(true); 
     Scene scene = new Scene(createContent()); 
     primaryStage.setTitle("Eric's Web Demo"); 
     scene.getStylesheets().add("style/template.css"); 
     primaryStage.setScene(scene); 
     primaryStage.show(); 
    } 
} 

的Web瀏覽器的GUI:

import org.w3c.dom.Attr; 
import org.w3c.dom.NodeList; 

import javafx.beans.value.ObservableValue; 
import javafx.collections.FXCollections; 
import javafx.collections.ListChangeListener.Change; 
import javafx.concurrent.Worker.State; 
import javafx.event.ActionEvent; 
import javafx.geometry.Dimension2D; 
import javafx.geometry.HPos; 
import javafx.geometry.Insets; 
import javafx.geometry.VPos; 
import javafx.scene.control.Button; 
import javafx.scene.control.ComboBox; 
import javafx.scene.control.Label; 
import javafx.scene.control.ProgressBar; 
import javafx.scene.control.TextField; 
import javafx.scene.layout.BorderPane; 
import javafx.scene.layout.GridPane; 
import javafx.scene.layout.HBox; 
import javafx.scene.layout.Priority; 
import javafx.scene.web.WebEngine; 
import javafx.scene.web.WebHistory; 
import javafx.scene.web.WebHistory.Entry; 
import javafx.scene.web.WebView; 

public class WebBrowser extends BorderPane { 

    private static final Dimension2D DIM = new Dimension2D(1220, 680); 
    private final WebView webView; 
    private final WebEngine webEngine; 
    private final ComboBox<String> addressBox; 
    private final TextField searchField; 
    private final Button backButton; 
    private final Button forwardButton; 
    private final Button proceedButton; 
    private final Button searchButton; 
    private final ProgressBar progressBar; 
    private final Label statusLabel; 

    public WebBrowser() { 

     this.setMinSize(DIM.getWidth(), DIM.getHeight()); 
     this.setPrefSize(DIM.getWidth(), DIM.getHeight()); 

     backButton = new Button("\uD83E\uDC78"); 
     backButton.setOnAction(this::backButtonListener); 

     forwardButton = new Button("\u2794"); 
     forwardButton.setDefaultButton(true); 
     forwardButton.setOnAction(this::forwardButtonListener); 

     proceedButton = new Button("Go"); 
     proceedButton.setOnAction(this::proceedButtonListener); 

     final HBox buttonGroup = new HBox(); 
     buttonGroup.setSpacing(5); 
     buttonGroup.setPadding(new Insets(10, 5, 10, 5)); 
     buttonGroup.getChildren().addAll(backButton, forwardButton, proceedButton); 

     addressBox = new ComboBox<String>(); 
     addressBox.setItems(FXCollections.observableArrayList()); 
     addressBox.setValue("http://stackoverflow.com/questions/32783532/applying-css-file-to-javafx-webview"); 
     addressBox.setOnAction(this::proceedButtonListener); 
     addressBox.setEditable(true); 
     addressBox.setMaxWidth(Double.MAX_VALUE); 

     searchField = new TextField(); 
     searchField.setPromptText("\uD83D\uDD0D Search"); 

     searchButton = new Button("\uD83D\uDD0D"); 
     searchButton.setDefaultButton(true); 
     searchButton.setOnAction(this::searchButtonListener); 

     statusLabel = new Label("Status: "); 
     progressBar = new ProgressBar(0); 

     webView = new WebView(); 
     webEngine = webView.getEngine(); 
     webEngine.load(addressBox.getValue()); 
     webEngine.getLoadWorker().stateProperty().addListener(this::stateChangeListener); 
     webEngine.locationProperty().addListener(this::urlChangeListener); 
     progressBar.progressProperty().bind(webEngine.getLoadWorker().progressProperty()); 

     final WebHistory history = webEngine.getHistory(); 
     history.getEntries().addListener(this::historyListener); 

     final GridPane root = new GridPane(); 
     GridPane.setConstraints(buttonGroup, 0, 0, 1, 1, HPos.LEFT, VPos.CENTER, Priority.NEVER, Priority.NEVER); 
     GridPane.setConstraints(addressBox, 1, 0, 1, 1, HPos.CENTER, VPos.CENTER, Priority.ALWAYS, Priority.NEVER); 
     GridPane.setConstraints(searchField, 2, 0, 1, 1, HPos.RIGHT, VPos.CENTER, Priority.NEVER, Priority.NEVER); 
     GridPane.setConstraints(searchButton, 3, 0, 1, 1, HPos.RIGHT, VPos.CENTER, Priority.NEVER, Priority.NEVER); 
     GridPane.setConstraints(webView,  0, 1, 4, 1, HPos.LEFT, VPos.CENTER, Priority.ALWAYS, Priority.ALWAYS); 
     GridPane.setConstraints(statusLabel, 0, 2, 1, 1, HPos.LEFT, VPos.CENTER, Priority.NEVER, Priority.NEVER); 
     GridPane.setConstraints(progressBar, 3, 2, 3, 1, HPos.RIGHT, VPos.CENTER, Priority.NEVER, Priority.NEVER); 
     GridPane.setMargin(addressBox, new Insets(5, 0, 5, 0)); 
     GridPane.setMargin(searchField, new Insets(5, 5, 5, 5)); 
     GridPane.setMargin(searchButton, new Insets(5, 8, 5, 0)); 
     GridPane.setMargin(statusLabel, new Insets(5, 0, 5, 5)); 
     GridPane.setMargin(progressBar, new Insets(5, 5, 5, 5)); 
     root.addRow(0, buttonGroup, addressBox, searchField, searchButton); 
     root.addRow(1, webView); 
     root.addRow(2,statusLabel, progressBar); 

     this.setCenter(root);  
    } 

    public void historyListener(Change<? extends Entry> changeValue) { 
     changeValue.next(); 
     for (Entry entry : changeValue.getRemoved()) { 
      addressBox.getItems().remove(entry.getUrl()); 
      System.out.print("Removed url: "); 
      System.out.println(entry.getUrl()); 
     } 
     for (Entry entry : changeValue.getAddedSubList()) { 
      System.out.print("Added url: "); 
      addressBox.getItems().add(entry.getUrl()); 
      System.out.println(entry.getUrl()); 
     } 
    } 

    public void progressBarListener(ObservableValue<? extends Number> ov, Number old_val, Number new_val) { 
     progressBar.setProgress(new_val.doubleValue()); 
    } 

    private void stateChangeListener(ObservableValue<? extends Object> observable, Object oldValue, Object newValue) { 

     setWebpageTheme(newValue == State.SUCCEEDED); 
     String output = newValue.toString().toLowerCase(); 
     statusLabel.setText("Status: " + output); 
    } 

    private void urlChangeListener(ObservableValue<? extends String> observable, String oldValue, String newValue) { 
     addressBox.setValue(newValue); 
    } 

    public void forwardButtonListener(ActionEvent event) { 
     webEngine.executeScript("history.forward()"); 
    } 

    private void backButtonListener(ActionEvent event) { 
     webEngine.executeScript("history.back()"); 
    } 

    private void searchButtonListener(ActionEvent event) { 
     String google = "http://www.google.com/search?q=" + searchField.getText(); 
     webEngine.load(google.startsWith("http://") || google.startsWith("https://") 
       ? google : "http://" + google); 
    } 

    private void proceedButtonListener(ActionEvent event) { 
     String url = addressBox.valueProperty().getValue(); 
     webEngine.load(url.startsWith("http://") || url.startsWith("https://") 
       ? url : "http://" + url); 
    } 

    private void setWebpageTheme(Boolean succeeded) { 
     // Can safely access DOM and set styles. 
     if (succeeded == true) { 
      // This gives the DOM Document for the web page. 
      NodeList htmlTags = webEngine.getDocument().getElementsByTagName("*"); 
      Attr newAttr = null; 
      for (int i = 0; i < htmlTags.getLength(); i++) { 
       newAttr = webEngine.getDocument().createAttribute("style"); 
       newAttr.setValue("background-color: #222; border-color: #333; background: #222; color: #bbb; "); 
       htmlTags.item(i).getAttributes().setNamedItem(newAttr); 
      } 
     } 
    } 
} 

文本文件路徑名:/style/template.css < -fx GUI設置(不適用於網頁的頁面)

.root{ 
    -fx-background: rgb(44,44,44); 
} 

.button { 
    -fx-border-radius: 5; 
    -fx-background-radius: 5; 
    -fx-min-height: 32; 
    -fx-min-width: 40; 
    -fx-background-color: radial-gradient(radius 100%, rgb(22, 33, 188), rgb(3,22,122)); 
    -fx-text-fill: rgb(196,188,222); 
} 

TextField { 
    -fx-border-radius: 5; 
    -fx-background-radius: 5; 
    -fx-max-height: 32; 
    -fx-min-width: 280; 
    -fx-border-color: #555; 
    -fx-border-width: 1 1 1 1; 
    -fx-background-color: #333; 
    -fx-text-fill: rgb(196,188,222); 
} 

.combo-box-base { 
    -fx-border-radius: 5; 
    -fx-background-radius: 5; 
    -fx-min-height: 35; 
    -fx-background-color: #333; 
    -fx-border-color: transparent; 
    -fx-border-width: 2 2 2 2; 
} 

.combo-box-base .arrow-button { 
    -fx-background-color: radial-gradient(radius 100%, rgb(22, 33, 188), rgb(3,22,122)); 
} 

.combo-box .combo-box-popup, .list-view, .list-cell { 
    -fx-background-color: #333; 
    -fx-text-fill: rgb(155,188,166); 
} 

.combo-box .text-input { 
    -fx-border-radius: 5; 
    -fx-background-radius: 5; 
    -fx-background-color: #333; 
    -fx-border-color: #555; 
    -fx-border-width: 1 1 1 1; 
    -fx-text-fill: rgb(155,188,166); 
} 

.scroll-bar { 
    -fx-background-color: #222; 
} 

.scroll-bar .thumb { 
    -fx-background-color: radial-gradient(radius 100%, rgb(22, 33, 188), rgb(3,22,122)); 
} 

.label { 
    -fx-font: 14px "Arial"; 
    -fx-border-color: rgb(57, 58, 59); 
    -fx-border-width: 2 2 2 2; 
    -fx-text-fill: rgb(155,188,166); 
} 

.progress-bar > .track { 
    -fx-text-box-border: rgb(44, 44, 44); 
    -fx-control-inner-background: rgb(22, 22, 44); 
} 

回答

0

我想出了一個解決方案,以儘量減少深色背景延遲的影響或具體的,th e無效,我將屬性添加到所有DOM html標籤。在調用方法setWebpageTheme(boolean succeed)之前,我使用下面的代碼添加了下面的html樣式表;它不是100%完美的,但是對於我的目的來說它是可以承受的。如果有人找到更好的解決方案,我仍然感興趣。

webEngine.setUserStyleSheetLocation(getClass().getResource("/style/style.css").toString()); 

的style.css

*, a, abbr, acronym, address, applet, b, big, blockquote, body, br, button, caption, center, cite, code, dd, del, dfn, div, 
dl, dt, element, em, em, fieldset, font, form, h1, h2, h3, h4, h5, h6, head, header, html, html, i, iframe, iframe, img, 
img, input, ins, kbd, label, label, legend, li, link, meta, nav, noscript, object, ol, ol, p, path, pre, q, s, samp, script, 
small, span, strike, strong, style, sub, sup, svg, table, tbody, td, textarea, tfoot, th, thead, title, tr, tt, u, ul, var { 
    background-color: #222; border-color: #333; background: #222; color: #bbb; 
}