Update of Create Browser using JavaFX Java by Rajesh Kumar Sahanee - May 11, 2020September 15, 20220 Post Views: 6,248 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 Browser.fxml XHTML <?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> 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192 <?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 BrowserController.java Java /* * 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(""); } } 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133 /* * 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 Main.java Java /* * 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); } } 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576 /* * 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 1 file(s) 123.36 KB Download Please don’t forget to share if you find this helpful