Is it possible to get the value of a HTML input inside a WebView in JavaFX?
If so, how would I use an event so the value updates automatically?
Example App:
package webviewinputvalue;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.StackPane;
import javafx.scene.web.WebEngine;
import javafx.scene.web.WebView;
import javafx.stage.Stage;
public class WebviewInputValue extends Application {
@Override
public void start(Stage primaryStage) {
WebView test = new WebView();
WebEngine run = test.getEngine();
run.loadContent("<textarea></textarea>");
StackPane root = new StackPane();
root.getChildren().add(test);
Scene scene = new Scene(root, 300, 250);
primaryStage.setTitle("Hello World!");
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
Which creates a simple window like this:
Question: Is it possible to get the value of the textarea using JavaFX? If so, how should I do it?
TL;DR: Yes, it's possible, but it requires a bit of a hacky workaround.
First of all, I'm going to move the HTML to it's own separate file, to make editing easier, and just create cleaner code in general.
editor.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Example Live-view</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
<textarea placeholder="Typing 'exit' will kill the program."></textarea>
<script>
document.querySelector("textarea").addEventListener("keyup", function(){
window.status = this.value;
});
</script>
</body>
</html>
The basic structure is really simple, but what about the <script>
element? What does it do?
document.querySelector("textarea").addEventListener("keyup", function(){
window.status = this.value;
});
AFAIK, it isn't possible to straight out get the value of an input in JavaFX, so you have to make a workaround. In this case, I'm setting the window status with the textarea value, whenever there is a keyup
event in the textarea.
Now we need to set up the webview in our JavaFX.
WebviewInputValue.java
package webviewinputvalue;
public class WebviewInputValue extends Application {
private WebView InitWebview(){
//Create browser
WebView browser = new WebView();
WebEngine render = browser.getEngine();
//Load simple HTML
String editor = WebviewInputValue.class.getResource("editor.html").toExternalForm();
render.load(editor);
//Listen for state change
render.getLoadWorker().stateProperty().addListener((ov, o, n) -> {
if (Worker.State.SUCCEEDED == n) {
render.setOnStatusChanged(webEvent -> {
//Call value change
onValueChange(webEvent.getData());
});
}
});
return browser;
}
//called when value changes
private void onValueChange(String data){
//Print out data
System.out.println(data);
//If the data is equal to "exit", close the program
if("exit".equals(data)){
//Print goodbye message
System.out.println("Received exit command! Goodbye :D");
//Exit
System.exit(0);
}
}
@Override
public void start(Stage primaryStage) {
//Create browser
WebView browser = InitWebview();
StackPane root = new StackPane();
root.getChildren().add(browser);
Scene scene = new Scene(root, 300, 250);
primaryStage.setTitle("Hello World!");
primaryStage.setScene(scene);
primaryStage.show();
}
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
launch(args);
}
}
Again, very simple code. Let's dig into it:
private WebView InitWebview(){
//Create browser
WebView browser = new WebView();
WebEngine render = browser.getEngine();
//Load simple HTML
String editor = WebviewInputValue.class.getResource("editor.html").toExternalForm();
render.load(editor);
//Listen for state change
render.getLoadWorker().stateProperty().addListener((ov, o, n) -> {
if (Worker.State.SUCCEEDED == n) {
render.setOnStatusChanged(webEvent -> {
//Call value change
onValueChange(webEvent.getData());
});
}
});
return browser;
}
First we create the webview and engine, then load the editor.html
file into the webview. Next, we fetch the loadWorker, which is what controls the window.status
object we are writing to with the JS. We then get the state
property, and add an listener. If the listener is added successfully, then listen for a change event.
When the change event, we'll call our onValueChange
method:
//called when value changes
private void onValueChange(String data){
//Print out data
System.out.println(data);
//If the data is equal to "exit", close the program
if("exit".equals(data)){
//Print goodbye message
System.out.println("Received exit command! Goodbye :D");
//Exit
System.exit(0);
}
}
This is extremely simple. onValueChange
is called with the textarea
value as the data
parameter. In this case, I'm printing it to the console. If I type exit
into the textarea, then it will print a goodbye message and close the application.
And that's it! If you run the above code, then it'll log the textarea value into the console real-time!
Note:
Your project structure should look this, with editor in the same dir as the java file, if you want this code to work straight off:
Also, I'm obviously missing the imports in the java code.
3 years later, but I hope it will help someone. I found how to get text from TextArea
without changing html page
Runnable check = () -> {
WebEngine engine = webView.getEngine();
if (engine != null) {
Document document = engine.getDocument();
if (document != null) {
Element element = document.getElementById("samlResponse");
if (element instanceof HTMLTextAreaElement) {
HTMLTextAreaElement textArea = (HTMLTextAreaElement) element;
String text = textArea.getValue();
if (text != null && !text.isEmpty()) {
System.out.println("BINGO:\n" + text);
System.exit(0);
}
}
}
}
};
new Thread(() -> {
while (true) {
Platform.runLater(check);
try {
Thread.sleep(1_000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();