当前位置: 首页 > 知识库问答 >
问题:

JavaFX在继续之前等待页面加载

任绪
2023-03-14

我有一个方法,可以为WebView的WebEngine设置一个新的网页,需要等到网页加载完成后才能继续使用当前方法。

基本上我想要:

MyMethod()
{
    navigateToNewUrl();
    waitForPageToLoad(); // This is the part I am struggling with
    doSomethingElse();
}

我尝试过使用ChangeListener(),但它只会在我的方法完成执行后执行。我在谷歌上搜索了许多导致更多挫折感的术语,比如“java非阻塞等待布尔值”。最终,我成功地启动了新线程(以防止应用程序GUI锁定)并使用了倒计时(与Thread.join()相反)。下面的代码是我第无数次尝试得到我想要的东西。

public static Boolean pageLoaded;
public volatile static CountDownLatch latch;

private static void TestMethod()
{
    // Set the CountDownLatch
    latch = new CountDownLatch(1);

    // Set the page loaded flag
    pageLoaded = false;

    // Navigate to new window
    myWebView.getEngine().load("https://www.google.com/");

    // Call a method, that starts a thread, that checks if the page has loaded
    WaitForPageLoaded();

    // Wait for the CountDownLatch, latch
    try { latch.await(); } catch (InterruptedException e) { /* TODO Auto-generated catch block */ e.printStackTrace(); }

    // Write result to console
    System.out.println("[pageLoaded] " + pageLoaded);
}

private static void WaitForPageLoaded()
{
    Thread thread = new Thread()
    {
        public void run()
        {
            // 120 iterations * 250 ms = 30 seconds
            for (int i = 0; i < 120; i++)
            {
                // Check if page has loaded
                if (pageLoaded == true)
                {
                    break;
                }
                else
                {
                    System.out.println("Waited " + (i*250) + " milliseconds, so far...");
                    try { Thread.sleep(250); }
                    catch (InterruptedException e) { /* TODO Auto-generated catch block */ e.printStackTrace(); }
                }
            }

            // Tell the calling method to move on with life
            latch.countDown();
        }
    }
}

另一方面。java文件(类)我有:

        // Get the WebEngine and set a listener for a state change
        WebEngine webEngine = webView.getEngine();
        webEngine.getLoadWorker().stateProperty().addListener
        (
            new ChangeListener<State>()
            {
                public void changed(@SuppressWarnings("rawtypes") ObservableValue ov, State oldState, State newState)
                {
                    if (newState == State.SUCCEEDED)
                    {
                        // Set the page loaded flag
                        OtherClassName.pageLoaded = true;
                    }
                }
            }
        );

共有1个答案

马祺
2023-03-14

与几乎所有的UI框架一样,JavaFX基于事件驱动模型。在幕后有一个循环(在FX应用程序线程中)运行,用于处理事件。你不应该直接处理这个循环。

您试图通过重新创建此循环并等待条件来解决问题,而不是注册响应适当事件的处理程序。而不是在一个线程中等待(哪个线程?没有明显的方法可以做到这一点)对于要加载的页面,您只需要响应完成加载的每个页面,并在测试过程中执行下一步。您可以通过在Web引擎的stateProperty上注册侦听器来实现这一点。

所以你的结构应该看起来像

public class MyApp extends Application {

    private WebView webView ;
    private WebEngine engine ;

    // variables representing the current state of your testing process...

    @Override
    public void start(Stage primaryStage) {

        webView = new WebView();
        engine = webView.getEngine();

        engine.getLoadWorker().stateProperty().addListener((obs, oldState, newState) -> {
            if (newState == Worker.State.SUCCEEDED) {
                // new page has loaded, process:
                testMethod();
            }
        });

        // set up UI etc...

        engine.load(...); // load first page

    }

    private void testMethod() {
        // check current state, do next appropriate thing, update variables...
    }

}

这个结构完全实现了您想要做的事情——testMethod()被反复调用,但只有当每个页面都完成加载时才会被调用——但是“等待”是由框架为您管理的。

 类似资料:
  • 我有一个加载页面,我想在其中对不相关的信息执行两个网络请求(rxjava)。在这两个请求完成之前,我不想进入下一页,即使其中一个或两个都失败了。 > 使用zip将请求绑定在一起。有没有办法不必被迫使用双函数,也不必返回null? 请求A和B有一个。doOnNext和。多恩。如果其中一个返回错误,zip observable是否继续?zip订阅服务器是否也会返回错误? 这是最好的方法吗?

  • 问题内容: 我正在尝试在Node.js / Express中创建一个路由,该路由从两个查询中读取数据,然后基于来自查询的数据来增加计数。由于Node.js是异步的,因此在读取所有数据之前会显示总计。 我创建了一个简单的示例,以达到我目前正在做的事情 我不确定要等到两个功能都完成后才能打印总计,我该做什么。我是否需要创建一个自定义事件发射器来实现这一目标? 问题答案: 拥抱异步性: 或使用Promi

  • 我试图创建一个等待加载页面的方法,但我出现了一个错误。可能我没有正确使用这个方法。 错误是:

  • 本文向大家介绍jQuery EasyUI 页面加载等待及页面等待层,包括了jQuery EasyUI 页面加载等待及页面等待层的使用技巧和注意事项,需要的朋友参考一下 下面一个代码片段是 easyUI 页面加载等待,代码如下所示: 下面看个工具类 基于easyui的页面等待提示层,即mask 效果图: 以上所述是小编给大家介绍的jQuery EasyUI 页面加载等待及页面等待层,希望对大家有所帮

  • 我正试图通过迁移当前使用Angular1/AngularJS编写的应用程序来提高我对Angular2的了解。 有一个特征特别难倒了我。我试图复制一个功能,其中调用函数等待继续,直到它正在调用的函数完成了一个循环的promise。在AngularJS中,我调用的函数基本上是这样的: 它包含一个调用另一个函数()的循环,该函数还返回一个promise,并将所有返回的promise存储在一个数组中。 使

  • 我有一个和一个事件,如果textbox的文本表示现有文件,则调用自定义事件。在这种情况下,会调用外部dll对文件进行一些处理,这可能需要一分钟以上的时间才能完成。我还做了一些后期处理,这取决于此方法返回给我的结果。目前,这是阻塞我的用户界面,这是非常不希望的。 我看到的基本上有两个“选项”/场景。 null 我还意识到我可以简化这些属性中的一些代码,以防止复制。为了给自己演示和调试,我现在暂时不做