Hello Friends, today I am going share an update of create Browser using JavaFX. Actually I was working on a JavaFX application which was making use of WebView but while testing I just browsed flipkart.com and suddenly it started showing “Something’s not right!” error then figured out and found that flipkart has CORS policy disabled for a domain to list products but JavaFX has same origin policy enabled by default. Then I googled and found a solution which I am sharing now. But wait story not ends here, after applying this solution I found another problem which was that while browsing flipkart, url was not reflecting in address bar but webpage was updating then again I googled and found that change listener on LocationProperty of webview is the solution for this problem. Finally I thought to share these solutions by creating update of an existing browser which I have developed and shared long time ago.
So, Here is solution
Browser.fxml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 |
<?xml version="1.0" encoding="UTF-8"?> <?import javafx.geometry.Insets?> <?import javafx.scene.control.Button?> <?import javafx.scene.control.Label?> <?import javafx.scene.control.ProgressIndicator?> <?import javafx.scene.control.TextField?> <?import javafx.scene.control.ToolBar?> <?import javafx.scene.control.Tooltip?> <?import javafx.scene.image.Image?> <?import javafx.scene.image.ImageView?> <?import javafx.scene.layout.BorderPane?> <?import javafx.scene.layout.HBox?> <?import javafx.scene.web.WebView?> <BorderPane fx:id="browserBP" minWidth="480.0" prefHeight="396.0" prefWidth="661.0" xmlns="http://javafx.com/javafx/8.0.101" xmlns:fx="http://javafx.com/fxml/1" fx:controller="browser.BrowserController"> <center> <BorderPane prefHeight="248.0" prefWidth="333.0"> <center> <WebView fx:id="browserWV" prefHeight="200.0" prefWidth="200.0" /> </center> <top> <ToolBar prefHeight="40.0" prefWidth="200.0" BorderPane.alignment="CENTER"> <items> <Button mnemonicParsing="false" onAction="#browserBackButtonAction"> <graphic> <ImageView fitHeight="16.0" fitWidth="16.0" pickOnBounds="true" preserveRatio="true"> <image> <Image url="@../images/back.png" /> </image> </ImageView> </graphic> <tooltip> <Tooltip text="Back" /> </tooltip> </Button> <Button mnemonicParsing="false" onAction="#browserForwardButtonAction"> <graphic> <ImageView fitHeight="16.0" fitWidth="16.0" pickOnBounds="true" preserveRatio="true"> <image> <Image url="@../images/forward.png" /> </image> </ImageView> </graphic> <tooltip> <Tooltip text="Forward" /> </tooltip> </Button> <Button mnemonicParsing="false" onAction="#browserStopReloadButtonAction"> <graphic> <ImageView fx:id="stopReloadIV" fitHeight="16.0" fitWidth="16.0" pickOnBounds="true" preserveRatio="true"> <image> <Image url="@../images/reload.png" /> </image> </ImageView> </graphic> </Button> <Button mnemonicParsing="false" onAction="#browserHomeButtonAction" > <graphic> <ImageView fitHeight="16.0" fitWidth="16.0" pickOnBounds="true" preserveRatio="true"> <image> <Image url="@../images/home.png" /> </image> </ImageView> </graphic> </Button> <HBox> <children> <TextField fx:id="addressBarTF" onAction="#browserGoButtonAction" prefHeight="26.0" prefWidth="492.0" /> <ProgressIndicator fx:id="progressPI" maxHeight="24.0" maxWidth="24.0" minHeight="16.0" minWidth="16.0" prefHeight="24.0" prefWidth="24.0" visible="false"> <HBox.margin> <Insets left="-24.0" /> </HBox.margin> </ProgressIndicator> </children> </HBox> </items> </ToolBar> </top> <bottom> <HBox BorderPane.alignment="CENTER"> <children> <Label fx:id="statusL" prefHeight="16.0" prefWidth="662.0" text="Status" /> </children> <BorderPane.margin> <Insets /> </BorderPane.margin> </HBox> </bottom> </BorderPane> </center> </BorderPane> |
BrowserController.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 |
/* * To change this license header, choose License Headers in Project Properties. * To change this template file, choose Tools | Templates * and open the template in the editor. */ package browser; import java.net.URL; import java.util.ResourceBundle; import javafx.beans.value.ChangeListener; import javafx.beans.value.ObservableValue; import javafx.concurrent.Worker; import javafx.event.ActionEvent; import javafx.fxml.FXML; import javafx.fxml.Initializable; import javafx.scene.control.Label; import javafx.scene.control.ProgressIndicator; import javafx.scene.control.Tab; import javafx.scene.control.TabPane; import javafx.scene.control.TextField; import javafx.scene.image.Image; import javafx.scene.image.ImageView; import javafx.scene.layout.BorderPane; import javafx.scene.web.WebView; import javax.swing.JOptionPane; /** * FXML Controller class * * @author rajesh */ public class BrowserController implements Initializable { @FXML BorderPane browserBP; @FXML WebView browserWV; @FXML ImageView stopReloadIV; @FXML TextField addressBarTF; @FXML ProgressIndicator progressPI; @FXML Label statusL; /** * Initializes the controller class. */ @Override public void initialize(URL url, ResourceBundle rb) { browserWV.getEngine().getLoadWorker().stateProperty().addListener(new ChangeListener<Worker.State>(){ @Override public void changed(ObservableValue<? extends Worker.State> observable, Worker.State oldValue, Worker.State newValue) { statusL.setText("loading... " + browserWV.getEngine().getLocation()); stopReloadIV.setImage(new Image(getClass().getResourceAsStream("/images/stoploading.png"))); progressPI.setVisible(true); if(newValue == Worker.State.SUCCEEDED) { addressBarTF.setText(browserWV.getEngine().getLocation()); statusL.setText("loaded"); progressPI.setVisible(false); stopReloadIV.setImage(new Image(getClass().getResourceAsStream("/images/reload.png"))); if(browserBP.getParent() != null) { TabPane tp = (TabPane)browserBP.getParent().getParent(); for(Tab tab : tp.getTabs()) { if(tab.getContent() == browserBP) { tab.setText(browserWV.getEngine().getTitle()); break; } } } } } }); browserWV.getEngine().locationProperty().addListener(new ChangeListener<String>() { @Override public void changed(ObservableValue<? extends String> ov, String t, String t1) { addressBarTF.setText(t1); } }); } @FXML private void browserBackButtonAction(ActionEvent event) { if(browserWV.getEngine().getHistory().getCurrentIndex() <= 0) { return; } browserWV.getEngine().getHistory().go(-1); } @FXML private void browserForwardButtonAction(ActionEvent event) { if((browserWV.getEngine().getHistory().getCurrentIndex() + 1) >= browserWV.getEngine().getHistory().getEntries().size()) { return; } browserWV.getEngine().getHistory().go(1); } @FXML private void browserGoButtonAction(ActionEvent event) { String url = addressBarTF.getText().trim(); if(url.isEmpty()) { JOptionPane.showMessageDialog(null, "No url provided"); return; } if(!url.startsWith("http://") && !url.startsWith("https://")) { url = "http://"+url; } browserWV.getEngine().load(url); //browserStopReloadIV.setImage(new Image(getClass().getResourceAsStream("/images/stoploading.png"))); } @FXML private void browserStopReloadButtonAction(ActionEvent event) { if(browserWV.getEngine().getLoadWorker().isRunning()) { browserWV.getEngine().getLoadWorker().cancel(); statusL.setText("loaded"); progressPI.setVisible(false); stopReloadIV.setImage(new Image(getClass().getResourceAsStream("/images/reload.png"))); } else { browserWV.getEngine().reload(); stopReloadIV.setImage(new Image(getClass().getResourceAsStream("/images/stoploading.png"))); } } @FXML private void browserHomeButtonAction(ActionEvent event) { browserWV.getEngine().loadContent("<html><title>New Tab</title></html>"); addressBarTF.setText(""); } } |
Main.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 |
/* * To change this license header, choose License Headers in Project Properties. * To change this template file, choose Tools | Templates * and open the template in the editor. */ package browser; import java.io.IOException; import java.util.logging.Level; import java.util.logging.Logger; import javafx.application.Application; import javafx.application.Platform; import javafx.event.Event; import javafx.event.EventHandler; import javafx.fxml.FXMLLoader; import javafx.scene.Parent; import javafx.scene.Scene; import javafx.scene.control.Tab; import javafx.scene.control.TabPane; import javafx.stage.Stage; import javafx.stage.WindowEvent; /** * * @author rajesh */ public class Main extends Application { TabPane root; @Override public void start(Stage stage) throws IOException { Parent browser = FXMLLoader.load(getClass().getResource("Browser.fxml")); Tab browserTab = new Tab("New Tab", browser); Tab addTab = new Tab("+", null); addTab.setClosable(false); addTab.setOnSelectionChanged(new EventHandler<Event>() { @Override public void handle(Event event) { addNewTab(); } }); root = new TabPane(browserTab, addTab); Scene scene = new Scene(root); stage.setOnCloseRequest(new EventHandler<WindowEvent>() { @Override public void handle(WindowEvent t) { Platform.exit(); System.exit(0); } }); stage.setScene(scene); stage.setTitle("Browser 2.0"); stage.show(); } final void addNewTab() { try { Parent browser = FXMLLoader.load(getClass().getResource("Browser.fxml")); Tab browserTab = new Tab("New Tab", browser); root.getTabs().add(root.getTabs().size() - 1, browserTab); root.getSelectionModel().select(browserTab); } catch (IOException ex) { Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex); } } /** * @param args the command line arguments */ public static void main(String[] args) { System.setProperty("sun.net.http.allowRestrictedHeaders", "true"); launch(args); } } |
Output/Screen Shot
Before allowRestrictedHeaders | Before LocationProperty Listener |
After allowRestrictedHeaders | After LocationProperty Listener |
Download NetBeans Project
Browser 2.0 NetBeans Project
Please don’t forget to share if you find this helpful
Comments