In JavaFX's WebView
I am struggling to detect change in URL.
I have this method in a class:
public Object urlchange() {
engine.getLoadWorker().stateProperty().addListener(new ChangeListener<State>() {
@Override
public void changed(ObservableValue ov, State oldState, State newState) {
if (newState == Worker.State.SUCCEEDED) {
return engine.getLocation());
}
}
});
}
and I am trying to use it for an object called loginbrowser like:
System.out.print(loginbrowser.urlchange());
Can you see what I've done wrong?
(Part of) what you are doing wrong
The code you provided in your question doesn't even compile. The changed method of a ChangeListener is a void function, it can't return any value.
Anyway, loading of stuff in a web view is an asynchronous process. If you want the value of the location of the web view after the web view has loaded, you need to either wait for the load to complete (inadvisable on the JavaFX application thread, as that would hang your application until the load is complete), or be notified in a callback that the load is complete (which is what the listener you have is doing).
(Probably) what you want to do
Bind some property to the location property of the web engine. For example:
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.layout.VBox;
import javafx.scene.web.*;
import javafx.stage.Stage;
public class LocationViewer extends Application {
@Override
public void start(Stage stage) throws Exception {
Label location = new Label();
WebView webView = new WebView();
WebEngine engine = webView.getEngine();
engine.load("http://www.fxexperience.com");
location.textProperty().bind(engine.locationProperty());
Scene scene = new Scene(new VBox(10, location, webView));
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
launch(args);
}
}
The above code will update the location label whenever the location of the web view changes (try it by running the code then clicking on some links). If you wish to only update the label once a page has successfully loaded, then you need a listener based upon the WebView state, for example:
import javafx.application.Application;
import javafx.concurrent.Worker;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.layout.VBox;
import javafx.scene.web.*;
import javafx.stage.Stage;
public class LocationAfterLoadViewer extends Application {
@Override
public void start(Stage stage) throws Exception {
Label location = new Label();
WebView webView = new WebView();
WebEngine engine = webView.getEngine();
engine.load("http://www.fxexperience.com");
engine.getLoadWorker().stateProperty().addListener((observable, oldValue, newValue) -> {
if (Worker.State.SUCCEEDED.equals(newValue)) {
location.setText(engine.getLocation());
}
});
Scene scene = new Scene(new VBox(10, location, webView));
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
launch(args);
}
}
If you run the last program and click on some links, you will notice it delays the updating of the location label until after the pages you click on completely finish loading, as opposed to the first program which updates the label as soon as the location changes, regardless of whether the load takes a while or indeed works at all.
Answers to additional questions
How can I use the url value in the label in a conditional statement? I want an action to be preformed if it changed from the original one.
location.textProperty().addListener((observable, oldValue, newValue) -> {
// perform required action.
});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With