JavaFX WebView with JavaScript Commands
I wanted to use JavaFX for web pages test like Selenium, but I realized I have not had enough knowledge about JavaFX. So I started to learn about WebView and WebEngine.
- Figure 1
WebView and 5 Buttons executing JavaScript commands
engine.load(...) starts a asynchronous loading and return immediately
WebView webView = new WebView(); engine = webView.getEngine(); engine.load("http://localhost:8080/HelloSample");
So the buttons should be disabled as long as the web page is loading, except first button
This code uses addListener method but there are some other ways (F.Y.R:JavaFX 2.2)
engine.getLoadWorker().stateProperty().addListener(new ChangeListener<Worker.State>() { @Override public void changed(ObservableValue<? extends State> ov, State oldState, State newState) { if (newState == State.SUCCEEDED && engine.getTitle().equalsIgnoreCase("Hello")) { btnHello.setDisable(false); btnMorning.setDisable(false); btnClear.setDisable(false); btnNotClear.setDisable(false); } else { btnHello.setDisable(true); btnMorning.setDisable(true); btnClear.setDisable(true); btnNotClear.setDisable(true); } } });
- Figure 2
After we click the [Greet Hello] button
add the below code to the button's setOnAction:
1. Input the JavaFX to text
2. click the Hello radio botton
3. select the English
4. click the greet button
public void handle(ActionEvent t) { engine.executeScript("document.getElementById('form1:name').value = 'JavaFX'"); engine.executeScript("document.getElementsByName('form1:greetSel')[0].checked = true"); engine.executeScript("document.getElementById('form1:language').options[0].selected = true"); engine.executeScript("var btn = document.getElementById('form1:greet'); btn.click();"); }
- Figure 3
After we click the [Greet おはよう] button
This code is almost the same to the Figure 2
public void handle(ActionEvent t) { engine.executeScript("document.getElementById('form1:name').value = 'JavaFX'"); engine.executeScript("document.getElementsByName('form1:greetSel')[1].checked = true"); engine.executeScript("document.getElementById('form1:language').options[1].selected = true"); engine.executeScript("var btn = document.getElementById('form1:greet'); btn.click();"); }
NOTE:
After Figure 2, I wanted to click [Greet おはよう] without clicking the [load Hello Screen] button.
But I could not find out the way about how to manage web page loading and control button handle method.
- Figure 4
When we uses browsers after click the [Clear Name] button
- can not open the confirm window like Figure 4
instead of this we have to use engine.setConfirmHandler method.
In this code shows how to control either ok or cancel button in the confirm window
I use the member variable isConfirmOK to do so, But I think there is another way....
btnClear.setOnAction(getClearNameAction(true)); // 「ClearName(OK)」button setting OK for confirm window btnNotClear.setOnAction(getClearNameAction(false)); // 「ClearName(cancel)」button setting Cancel for confirm window ... private EventHandler<ActionEvent> getClearNameAction(final boolean isOK) { return new EventHandler<ActionEvent>() { @Override public void handle(ActionEvent t) { isConfirmOK = isOK; engine.executeScript("var btn = document.getElementById('form1:clearButton'); btn.click();"); } }; } ..... engine.setConfirmHandler(getConfirmAction()); ...... private Callback<String, Boolean> getConfirmAction() { return new Callback<String, Boolean>() { @Override public Boolean call(String p) { if (isConfirmOK) { return true; } return false; } }; }
Please feel free to give me any advice anytime.
- all the code here
package test; import javafx.application.Application; import javafx.beans.value.ChangeListener; import javafx.beans.value.ObservableValue; import javafx.concurrent.Worker; import javafx.concurrent.Worker.State; import javafx.event.ActionEvent; import javafx.event.EventHandler; import javafx.geometry.Insets; import javafx.scene.Scene; import javafx.scene.control.Button; import javafx.scene.layout.HBox; import javafx.scene.layout.VBox; import javafx.scene.web.WebEngine; import javafx.scene.web.WebView; import javafx.stage.Stage; import javafx.util.Callback; /** * * @author tomo */ public class HelloSampleTest extends Application{ private WebEngine engine; private boolean isConfirmOK; @Override public void start(Stage stage) throws Exception { WebView webView = new WebView(); engine = webView.getEngine(); engine.load("http://localhost:8080/HelloSample"); VBox box = new VBox(); box.getChildren().add(webView); Button btnLoad = new Button("load Hello Screen"); final Button btnHello = new Button("Greet Hello"); btnHello.setDisable(true); final Button btnMorning = new Button("Greet おはよう"); btnMorning.setDisable(true); final Button btnClear = new Button("clearName(OK)"); btnClear.setDisable(true); final Button btnNotClear = new Button("clearName(cancel)"); btnNotClear.setDisable(true); engine.getLoadWorker().stateProperty().addListener(new ChangeListener<Worker.State>() { @Override public void changed(ObservableValue<? extends State> ov, State oldState, State newState) { if (newState == State.SUCCEEDED && engine.getTitle().equalsIgnoreCase("Hello")) { btnHello.setDisable(false); btnMorning.setDisable(false); btnClear.setDisable(false); btnNotClear.setDisable(false); } else { btnHello.setDisable(true); btnMorning.setDisable(true); btnClear.setDisable(true); btnNotClear.setDisable(true); } } }); HBox hbox = new HBox(); hbox.setPadding(new Insets(15,12,15,12)); hbox.setSpacing(10); hbox.setStyle("-fx-background-color: #336699;"); hbox.getChildren().addAll(btnLoad, btnHello, btnMorning, btnClear, btnNotClear); box.getChildren().add(hbox); btnLoad.setOnAction(getLoadAction()); btnHello.setOnAction(getHelloAction()); btnMorning.setOnAction(getおはようAction()); btnClear.setOnAction(getClearNameAction(true)); btnNotClear.setOnAction(getClearNameAction(false)); engine.setConfirmHandler(getConfirmAction()); stage.setScene(new Scene(box, 800, 300)); stage.show(); } private EventHandler<ActionEvent> getLoadAction() { return new EventHandler<ActionEvent>() { @Override public void handle(ActionEvent t) { engine.load("http://localhost:8080/HelloSample"); } }; } private EventHandler<ActionEvent> getHelloAction() { return new EventHandler<ActionEvent>() { @Override public void handle(ActionEvent t) { engine.executeScript("document.getElementById('form1:name').value = 'JavaFX'"); engine.executeScript("document.getElementsByName('form1:greetSel')[0].checked = true"); engine.executeScript("document.getElementById('form1:language').options[0].selected = true"); engine.executeScript("var btn = document.getElementById('form1:greet'); btn.click();"); } }; } private EventHandler<ActionEvent> getおはようAction() { return new EventHandler<ActionEvent>() { @Override public void handle(ActionEvent t) { engine.executeScript("document.getElementById('form1:name').value = 'JavaFX'"); engine.executeScript("document.getElementsByName('form1:greetSel')[1].checked = true"); engine.executeScript("document.getElementById('form1:language').options[1].selected = true"); engine.executeScript("var btn = document.getElementById('form1:greet'); btn.click();"); } }; } private EventHandler<ActionEvent> getClearNameAction(final boolean isOK) { return new EventHandler<ActionEvent>() { @Override public void handle(ActionEvent t) { isConfirmOK = isOK; engine.executeScript("var btn = document.getElementById('form1:clearButton'); btn.click();"); } }; } private Callback<String, Boolean> getConfirmAction() { return new Callback<String, Boolean>() { @Override public Boolean call(String p) { if (isConfirmOK) { return true; } return false; } }; } public static void main(String... args) { launch(args); } }
The code is hosted on gist JavaFX using WebView · GitHub
So keep coding....