So I been stuck on this problem for a while now and have not been able to come up with a solution that works without bugs. Basically I have this code:
public void startExp() {
root.setCenter(webView);
//length depends on the exp selected
for (String expMode : expModes) {
int r = -1;
for (int j = 0; j < 2; j++) { // This is the # of the times I would like the same experiment/html page load)
int temp = r;
while (r == temp)
r = ThreadLocalRandom.current().nextInt(0, 2);
String mode = expMode + ".html";
System.out.println(mode);
url = this.getClass().getResource(mode);
webEngine.getLoadWorker().stateProperty().addListener(
(ov, oldState, newState) -> {
if (newState == Worker.State.SUCCEEDED) {
System.out.println("here");
webEngine.executeScript("timer('passage');");
// webEngine.executeScript("move('" + textBold + "');");
// window.setMember("invoke", new change());
}
}
);
webEngine.load(url.toString());
// Want this loop to pause here until the JS function finishes executing in webview
}
}
}
I want the for loop to somehow "pause" until the javascript function finishes executing and then continue again. The reason I need a for loop and webview for this, is because I need to repeat a given set of experiments (that continuously updates the GUI) that could only (it was also easier) be coded through embedding html pages.
For reference, this is one of the html pages where the JS function takes a string variable from the java function 'startExp()':
<!DOCTYPE html>
<html lang="en">
<head>
<title>Hello World</title>
<link rel="stylesheet" href="./style.css">
</head>
<body>
<p id="demo"></p>
<script type="application/javascript">
let i = 0;
function timer(a) {
const splitted = a.split(" ");
const timerID = setInterval(function() {highlight()} , 500);
function highlight() {
if (i == splitted.length) {
clearInterval(timerID);
invoke.change();
}
let markS = "<mark>";
let markE = "</mark>";
let temp = splitted[i];
splitted[i] = markS + splitted[i] + markE;
let passage = splitted.join(" ");
document.getElementById("demo").innerHTML = passage;
splitted[i] = temp;
i = i + 1;
}
}
</script>
</body>
</html>
Also for reference, the variables:
BorderPane root;
static WebView webView ;
static WebEngine webEngine;
static String[] expModes = {"porbTest", "highlightWordsTest"};
String passage = "this is passage 1 and we are seeing if this works. Right now it doesn't but one day it will.";
I tried taking the multithreading approach and using Thread.join() but found out that the webview can only be updated in the Javafx application thread.
Thread.sleep() also doesn't work for me since it sleeps the GUI too (but I need the gui to be updated).
Platform.runlater() defeats the purpose of the for loop since the application goes through the whole for loop and then only runs the last 'mode', this also only works 1% of the time.
I would appreciate if I could get some insight into how I can make this possible .
Thank you