在JavaFX WebView中打开不同的网站(更新用户界面?)

时间:2018-02-04 00:19:08

标签: javafx webview

我尝试在给定时间后将不同的网址加载到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>

我在/ * * /中首先使用了第二个&#34; urlLoad&#34; -Method(FXMLController.java),但认识到所有链接都是立即加载的,只有最后一个链接保持活动状态。之后我添加了#34; Thread.sleep(urlTime)+ try&amp;捉&#34;但它冻结了我的整个GUI,直到加载了最后一个URL。在寻找解决方案时,这是我第一次听说工人,任务和工作。服务。 我发现了为什么会这样,并试图添加一个&#34;任务&#34;围绕代码。在我找到FXMLController.java中第一个&#34; urlLoad&#34; -Method的代码之前,这是一个漫长的过程。这正是我与Urls的代码所做的事情

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

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

然后我将我的engine.load()部分添加到第一个&#34; urlLoad&#34; -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个声望应该有一个图像

我的假设是,&#34; urlLoad&#34; -Method不会更新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

1 个答案:

答案 0 :(得分:0)

你需要使用

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

Javafx对于它允许您在哪个线程中运行的操作非常小气。从本质上讲,你没有业务运行在非ui线程上为ui控制功能指定的代码...因此&#34;线程5&#34;在你的情况下。

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

所以...

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

线程5(随意运行)

- &GT;

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

主题5(调用platform.runlater(/ * engine.load(&#34; x&#34;)* /))

- &GT;

javafxapplicationthread(执行engine.load())

线程5(等等等)

祝你好运