【问题标题】:JavaFX/SWT WebView synchronous loadcontent()JavaFX/SWT WebView 同步 loadcontent()
【发布时间】:2016-04-26 06:02:15
【问题描述】:

我在 Eclipse SWT 应用程序中嵌入了 JavaFX 的 WebView,需要加载 html 内容。 我需要阻止当前线程的执行,直到 web 引擎完成加载内容。任何熟悉这种情况并可以提供一些提示和/或最佳实践来实现这一点的人? SWT 和 JavaFX 似乎都运行在同一个 UI 线程中。

谢谢!

【问题讨论】:

    标签: java webview swt javafx


    【解决方案1】:

    加载未完成时显示模式窗口。您不能阻塞应用程序线程,因为 SWT/JavaFX 操作相同

    【讨论】:

    • 感谢您的提示,汤姆!我正在使用 SWT 的 BusyIndi​​cator 而不是模式对话框。
    • 除了忙碌指示符之外,我决定将后续浏览器命令收集到队列中,而不是立即执行它们。加载完成后,将处理该队列。另请参阅此相关问题:stackoverflow.com/questions/33971137/…
    【解决方案2】:

    JavaFX 网络引擎在每个实现中异步加载。 loadworker 的 stateproperty 的任何侦听器都会在 JavaFX 线程上接收回调。这个线程也运行你的 UI,这就是为什么你永远不应该阻塞 JavaFX 线程。在 JavaFX 等基于事件的 UI 系统中,如果您想做一些繁重的工作,您可以在自己的线程中执行此操作。永远不要阻塞 JavaFX 线程。

    我回答的原因是因为我实际上有一个类似但不同的情况,我确实需要同步加载。我的第一个想法是将负载包装在我自己的线程中并制作该块,但需要从 JavaFX 线程调用加载操作。不过,我想出了一个绕过这个障碍的方法:

    首先,我启动一个新线程,在其中声明一个信号量(许可为 0),从该线程启动一个启动引擎的 Platform.runLater(...),向 stateproperty 添加一个侦听器并加载一个 URL,然后通过尝试获取信号量。这会阻塞,因为信号量没有许可。在侦听器的回调中,我启动另一个新线程,我在其中完成繁重的工作,并从那里设置一些全局数据变量,然后释放信号量。这终止了我的后一个新线程,然后通知前一个新线程数据已加载,因此它可以继续。这也不会阻塞 JavaFX 线程。

    将其包装在函数中时,您可以模拟同步加载操作,但使用时应谨慎:仅从 JavaFX 线程外部调用该函数。但是,这很有意义,因为您永远不应该在 JavaFX 线程上调用同步(也称为阻塞)加载。

    【讨论】:

      【解决方案3】:

      我遇到了同样的问题,我需要从某个页面以同步方式加载 HTML,所以我想出了以下解决方案:

      import org.w3c.dom.Document;
      
      import javafx.application.Application;
      import javafx.beans.value.ChangeListener;
      import javafx.beans.value.ObservableValue;
      import javafx.scene.Scene;
      import javafx.scene.web.WebView;
      import javafx.stage.Stage;
      
      public class SynchronousExample  extends Application {
      
      private static String HTML = "";
      private static Stage stage;
      
      @Override
      public void start(Stage primaryStage) throws Exception {
          System.out.print( SynchronousExample.loadUrl("http://google.com") );
      
      }
      
      public static void main(String[] args){
          launch(args);
      }
      
      private static void attachDocumentPropertyListener(WebView webView){
          webView.getEngine().documentProperty().addListener(new ChangeListener<Document>() {
                @Override public void changed(ObservableValue<? extends Document> prop, Document oldDoc, Document newDoc) {
                  String html = webView.getEngine().executeScript(
                    "document.documentElement.outerHTML"
                  ).toString();
      
                  HTML = html;
                  //after page load autmatically close the window
                  if(stage != null){
                      stage.close();
                  }
                }
              });
      }
      
      public static String loadUrl(String url){
          WebView webView = new WebView();
          attachDocumentPropertyListener(webView);
          webView.getEngine().load(url);
          stage = new Stage();
          Scene scene = new Scene(webView);
          stage.setWidth(1);
          stage.setHeight(1);
          stage.setScene(scene);
          stage.showAndWait();
          // here HTML will be available
          return HTML;
      }
      
      }
      

      【讨论】:

        猜你喜欢
        • 2013-10-16
        • 2015-12-17
        • 1970-01-01
        • 2018-09-05
        • 1970-01-01
        • 1970-01-01
        • 2018-08-19
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多