【发布时间】: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添加到您的任务中,以检查它是否抛出任何异常。