【问题标题】:Opening different websites in JavaFX WebView (Update UI?)在 JavaFX WebView 中打开不同的网站(更新 UI?)
【发布时间】:2018-02-04 00:19:08
【问题描述】:

我正在尝试在给定时间后将不同的 url 加载到 javafx webview 中。我已经搜索了至少 2 周的解决方案,但我找不到任何东西或无法将类似问题的解决方案转移到我的代码中。以下是代码的必要部分:

Main.java

package application;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.stage.Stage;
import javafx.scene.Parent;
import javafx.scene.Scene;

public class Main extends Application {

    @Override
    public void start(Stage primaryStage) {

    try {
        Parent root = FXMLLoader.load(getClass().getResource("/application/FXML.fxml"));

        primaryStage.setTitle("Window");
        primaryStage.setScene(new Scene (root));
        primaryStage.show();

    } catch(Exception e) {
        e.printStackTrace();
    }   
}

    public static void main(String[] args) {
    launch(args);
    }
}

FXMLController.java

package application;
import java.io.File;
import java.net.URL;
import java.nio.file.Files;
import java.util.List;
import java.util.ResourceBundle;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.concurrent.Task;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Button;
import javafx.scene.control.Slider;
import javafx.scene.web.WebEngine;
import javafx.scene.web.WebView;
import javafx.stage.FileChooser;
import javafx.stage.FileChooser.ExtensionFilter;


public class FXMLController implements Initializable {

    @FXML private Button btnAddUrl;
    @FXML private Button btnStart;
    @FXML private Slider sliderTime2NextUrl;
    @FXML private WebView webviewWindow;

    private WebEngine engine;
    private FileChooser fileChooser;
    private List<String> url;
    private int urlTime;

    public void initialize(URL arg0, ResourceBundle arg1) {     
        btnAddUrl.setOnAction(this::addUrls);
        btnStart.setOnAction(this::urlLoad);
        fileChooser = new FileChooser();
        engine = webviewWindow.getEngine();
        getsliderTime2NextUrl();
    }//initialize

    @FXML
    private void addUrls(ActionEvent event) {
        fileChooser.setTitle("Add Like List");
        fileChooser.getExtensionFilters().addAll(
            new ExtensionFilter("TXT Files", "*.TXT"),  
            new ExtensionFilter("txt Files", "*.txt"));
        File file = fileChooser.showOpenDialog(null);
        try {
              url = Files.readAllLines(file.toPath());
        }     catch (Exception e) { 
              System.out.println("shit");
        }
        System.out.println(url);
    }

    @FXML
    private void getsliderTime2NextUrl() {  
        sliderTime2NextUrl.valueProperty().addListener(new ChangeListener<Number>() {            
         @Override
         public void changed(ObservableValue<? extends Number> observable, Number oldValue, Number newValue) { 
             System.out.println("Slider Value Changed (newValue: " + newValue.intValue() + ")");
             double  getTime;
             getTime = sliderTime2NextUrl.valueProperty().getValue();
             urlTime = (int)  getTime;
         }//changed
        });//addListener
    }//getsliderTime2NextUrl


    @FXML
    private void urlLoad (ActionEvent event)  { 
        Task<Void> task = new Task<Void>() {
            @Override protected Void call() throws Exception{

                urlTime = urlTime * 1000 ;
                System.out.println("next Url in: " + urlTime);
                for(int i = 0; i < url.size(); i++) {
                    System.out.println("Url.size = "+ url.size());
                    System.out.println("Url = "+ i);    

                    if(isCancelled()) {
                        updateMessage("Cancelled");
                        break;
                    }
                    updateMessage("Iteration " + i);
                    updateProgress(i, 1000);

                    try {
                        Thread.sleep(urlTime);
                        System.out.println("Thread Sleeps for :" + urlTime);
                    } catch (InterruptedException interrupted) {
                          if (isCancelled()) {
                              updateMessage("Cancelled");
                              break;
                      }
                    }
                }
                return null;
            }
        };

        new Thread(task).start();
    }

    /*
    @FXML
    private void urlLoad (ActionEvent event)  { 
        urlTime = urlTime * 1000 ;
        System.out.println("next Url in: " + urlTime);

        for(int i = 0; i < url.size(); i++) {
            System.out.println("Url.size = "+ url.size());
            System.out.println("Url = "+ i);    
            String Link = url.get(i);
            engine.load(Link);
            System.out.println("Url loaded = " + Link);
        }
    }*/

}   

FXML.fxml

 <?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.web.*?>
<?import javafx.scene.text.*?>
<?import javafx.scene.control.*?>
<?import java.lang.*?>
<?import javafx.scene.layout.*?>

<AnchorPane maxHeight="1.7976931348623157E308"
maxWidth="1.7976931348623157E308" 
minHeight="400.0" minWidth="500.0" 
prefHeight="500.0" prefWidth="500.0" 
xmlns="http://javafx.com/javafx/8"         
xmlns:fx="http://javafx.com/fxml/1"
fx:controller="application.FXMLController">
   <children>
      <MenuBar maxHeight="25.0" maxWidth="1920.0" prefHeight="25.0" prefWidth="500.0">
         <menus>
            <Menu mnemonicParsing="false" text="File">
           <items>
              <MenuItem mnemonicParsing="false" text="Close" />
           </items>
        </Menu>
        <Menu mnemonicParsing="false" text="Edit">
           <items>
              <MenuItem mnemonicParsing="false" text="Delete" />
           </items>
        </Menu>
        <Menu mnemonicParsing="false" text="Help">
           <items>
              <MenuItem mnemonicParsing="false" text="About" />
           </items>
        </Menu>
     </menus>
  </MenuBar>
  <Button fx:id="btnAddUrl" layoutX="66.0" layoutY="39.0" mnemonicParsing="false" onAction="#addUrls" prefHeight="25.0" prefWidth="69.0" text="AddUrl" />
  <Button fx:id="btnStart" layoutX="36.0" layoutY="108.0" mnemonicParsing="false" onAction="#urlLoad" prefHeight="31.0" prefWidth="108.0" text="Start!">
     <font>
        <Font size="18.0" />
     </font>
  </Button>
  <Slider fx:id="sliderTime2NextUrl" blockIncrement="1.0" layoutX="204.0"     layoutY="39.0" majorTickUnit="2.0" max="15.0" min="3.0" minorTickCount="1"     prefHeight="38.0" prefWidth="251.0" showTickLabels="true"     showTickMarks="true" snapToTicks="true" value="3.0" />
 <WebView fx:id="webviewWindow" layoutY="147.0" minHeight="-1.0"     minWidth="-1.0" prefHeight="350.0" prefWidth="500.0" />
   </children>
</AnchorPane>

我首先在 /* */ 中使用了第二个“urlLoad”-Method (FXMLController.java),但认识到所有链接都立即加载,只有最后一个保持活动状态。之后我添加了“Thread.sleep(urlTime) + try & catch”,但它冻结了我的整个 GUI,直到最后一个 URL 被加载。在寻找解决方案时,那是我第一次听说工人、任务和服务。 我找到了发生这种情况的原因并尝试在代码周围添加一个“任务”。直到我在 FXMLController.java 中找到第一个“urlLoad”方法的代码之前,这是一个漫长的过程。这正是我的 Urls 代码应该做的事情

![urlLoad-Method 1] 如果我有 10 个声望,应该有一个图像

它会在给定时间从滑块中给出控制台中的数字。

然后我将我的 engine.load() 部分添加到第一个“urlLoad”-Method

 //updateMessage("Iteration " + i);
 //updateProgress(i, 1000);
 String Link = url.get(i);
 engine.load(Link);
 System.out.println("Url loaded = " + Link);

但随后该方法在第一个 Url 处停止并且不显示任何内容:

![urlLoad-Method 1 with engine.load] 如果我有 10 个声望,应该有一个图像

我的假设是,“urlLoad”-方法不会更新我的 GUI 中的 WebView 窗口。我希望有人可以帮助我。

谢谢

编辑:添加后

task.setOnFailed((WorkerStateEvent t) -> {
        throw new RuntimeException(task.getException());
    });

我遇到了以下异常:

Exception in thread "JavaFX Application Thread" java.lang.RuntimeException: java.lang.IllegalStateException: Not on FX application thread; currentThread = Thread-5
at application.FXMLController.lambda$2(FXMLController.java:111)
at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:86)
at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:238)
at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191)
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:54)
at javafx.event.Event.fireEvent(Event.java:198)
at javafx.concurrent.EventHelper.fireEvent(EventHelper.java:219)
at javafx.concurrent.Task.fireEvent(Task.java:1356)
at javafx.concurrent.Task.setState(Task.java:707)
at javafx.concurrent.Task$TaskCallable.lambda$call$502(Task.java:1453)
at com.sun.javafx.application.PlatformImpl.lambda$null$172(PlatformImpl.java:295)
at java.security.AccessController.doPrivileged(Native Method)
at com.sun.javafx.application.PlatformImpl.lambda$runLater$173(PlatformImpl.java:294)
at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95)
at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
at com.sun.glass.ui.win.WinApplication.lambda$null$147(WinApplication.java:177)
at java.lang.Thread.run(Unknown Source)
 Caused by: java.lang.IllegalStateException: Not on FX application thread; currentThread = Thread-5
at com.sun.javafx.tk.Toolkit.checkFxUserThread(Toolkit.java:279)
at com.sun.javafx.tk.quantum.QuantumToolkit.checkFxUserThread(QuantumToolkit.java:423)
at javafx.scene.web.WebEngine.checkThread(WebEngine.java:1243)
at javafx.scene.web.WebEngine.load(WebEngine.java:913)
at application.FXMLController$2.call(FXMLController.java:92)
at application.FXMLController$2.call(FXMLController.java:1)
at javafx.concurrent.Task$TaskCallable.call(Task.java:1423)
at java.util.concurrent.FutureTask.run(Unknown Source)
... 1 more

【问题讨论】:

  • setOnFailed 添加到您的任务中,以检查它是否抛出任何异常。

标签: javafx webview


【解决方案1】:

你需要使用

Platform.Runlater(()->{/*your task content here*/});

Javafx 对它允许您在哪个线程中运行哪些操作很恼火。本质上,您没有为非 ui 线程上的 ui 控制功能指定的业务运行代码......因此在您的情况下为“线程 5”。

但是要小心,因为您仍然需要后台线程中的 thread.sleep 例程,因为 javafx 线程将休眠,然后继续执行 url.load() 例程。

所以...


javafxapplication 线程(运行 - 处理自己的操作)

线程 5(运行任何你想要的)

->

javafxapplication 线程(运行但从您的 POV 空闲)

线程 5(调用 platform.runlater(/* engine.load("x") */))

->

javafxapplicationthread(执行engine.load())

线程 5(等等等等)


祝你好运

【讨论】:

    猜你喜欢
    • 2016-06-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-11
    • 1970-01-01
    相关资源
    最近更新 更多