2017-02-23 3 views
0

Mit JavaFX Webview, ändere ich mehrere HTML-Attribute (Hintergrund, Rahmen und Farbe) für alle Website DOM-Tags weltweit. Meine Absicht ist, ein angepasstes dunkles Thema zu haben, das sehr ähnlich wie ein hoher Kontrast Einstellungen würde. Das einzige Problem, das ich nicht lösen kann, ist die leichte Verzögerung, die der Code in der letzten Methode setWebpageTheme (Boolean succeed) erzeugt. Es führt zu einem hellen weißen Flackern, wenn die html css-Attribute angewendet werden und die weißen zu dunklen Seitenhintergründen ändern. Bitte beachten Sie den vollständigen Code unten.JavaFX webview global CSS dunkles Thema

Hauptklasse:

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-Browser 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); 
      } 
     } 
    } 
} 

Textdatei-Pfadname: /style/template.css < -fx GUI-Einstellungen (nicht für Web-Seiten)

.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); 
} 

Antwort

0

ich mit einer Lösung zu kommen haben die Auswirkungen der dunklen Hintergrund Verzögerung zu minimieren oder um genau zu sein, th Ineffizienz, in der ich allen DOM-HTML-Tags Attribute hinzufüge. Ich habe das folgende html-Stylesheet mit dem folgenden Code vor dem Aufruf der Methode setWebpageTheme (boolean succeed) hinzugefügt; Es ist nicht 100% perfekt, aber es ist für meine Zwecke erträglich. Wenn jemand eine bessere Lösung findet, bin ich immer noch interessiert.

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; 
}