2013-10-08 2 views
2

У меня встроенный WebView Web-приложения JavaFX в приложении Eclipse SWT и вам нужно загрузить содержимое html. Мне нужно заблокировать выполнение текущего потока, пока веб-сервер не завершит загрузку содержимого. Любой, кто знаком с этим сценарием и может дать некоторые рекомендации и/или передовые методы для достижения этого? Кажется, что и SWT, и JavaFX работают в одном и том же потоке пользовательского интерфейса.JavaFX/SWT WebView synchronous loadcontent()

Спасибо!

ответ

1

Показывать модальное окно, пока загрузка еще не закончена. Вы не можете заблокировать поток приложений, так как SWT/JavaFX работают на одном и том же

+0

Спасибо за подсказку, Том! Я использую SWT BusyIndicator вместо модального диалога. –

+0

В дополнение к индикатору занятости я решил собрать мои последующие команды браузера в очереди, а не сразу их выполнить. По завершении загрузки эта очередь будет обработана. Также см. Этот родственный вопрос: http://stackoverflow.com/questions/33971137/how-to-wait-for-webengine-browser-initialization-in-javafx-application/33981584#33981584 – Stefan

1

Веб-сайт JavaFX загружается асинхронно на реализацию. Любой слушатель состояния состояния loadworker получает обратный вызов в потоке JavaFX. Этот поток также запускает ваш пользовательский интерфейс, поэтому вы никогда не должны блокировать поток JavaFX. В системах на основе событий, таких как JavaFX, если вы хотите сделать тяжелую работу, вы сделаете это в своем потоке. Никогда, никогда не блокируйте поток JavaFX.

Причина, по которой я отвечаю, состоит в том, что у меня на самом деле есть аналогичная, но другая ситуация, в которой я нуждаюсь в синхронности нагрузки do. Моя первая идея заключалась в том, чтобы обернуть загрузку в моем собственном потоке и сделать этот блок, но операцию загрузки нужно вызывать из потока JavaFX. Тем не менее, я выяснил путь вокруг этого препятствия:

Сначала я начинаю новую тему, в которой я объявляю семафор (с разрешениями 0), откуда я запускаю Platform.runLater (...), который инициирует движок, добавляет слушателя к stateproperty и загружает URL-адрес, а затем пытается приобрести семафор. Это блокирует, поскольку семафор не имеет разрешений. В обратном вызове слушателя я запускаю еще один новый поток, в котором выполняю тяжелую работу, и оттуда я установил некоторую глобальную переменную данных, после чего я освобожу семафор. Это завершает мой последний новый поток, а затем информирует прежний новый поток, что данные загружаются, чтобы он продолжался. Это никогда не блокирует поток JavaFX.

При обертывании этой функции вы можете эмулировать операцию синхронной загрузки, но при ее использовании вы должны быть осторожны: вызовите функцию только из потока JavaFX. Однако это имеет смысл, потому что вы никогда не должны называть синхронную (ака блокирующую) нагрузку на поток JavaFX.

0

У меня была такая же проблема, и мне нужно, чтобы загрузить 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; 
} 

}