[英]Start and stop JavaFX background thread with 2 buttons
我正在尝试制作一个简单的UI来启动硒测试,该硒测试能够启动后台线程,该后台线程在按下“开始”按钮时启动浏览器,并在按下“停止”按钮时停止该线程并关闭它。 不幸的是,当我在启动后单击停止时,它不起作用。 如果结束,则无法重新启动线程。 我将如何进行更新,以便使它提交可以由“停止”按钮停止的新线程。
package application;
import org.openqa.selenium.WebDriver;
import javafx.application.Application;
import javafx.concurrent.Task;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.GridPane;
public class Main extends Application {
Stage window;
GridPane grid;
public void start(Stage primaryStage) {
/*
* Set up the stage
*/
window = primaryStage;
window.setTitle("URL LOADER - V1");
grid = new GridPane();
grid.setPadding(new Insets(10,10,10,10));
grid.setVgap(8);
grid.setHgap(10);
window.setResizable(false);
/*
* URL input
*/
Label URLLabel = new Label("URL");
GridPane.setConstraints(URLLabel,0,0);
TextField URLTextField = new TextField();
URLTextField.setPromptText("https://www.google.com");
GridPane.setConstraints(URLTextField,1,0);
/*
* Create Buttons
*/
Button buttonStart = new Button("Create");
GridPane.setConstraints(buttonStart,1,6);
Button buttonStop = new Button("Stop");
GridPane.setConstraints(buttonStop,1,8);
grid.getChildren().addAll(URLLabel,URLTextField, buttonStart, buttonStop);
/*
* Create the scene
*/
Scene scene = new Scene(grid, 300, 300);
window.setScene(scene);
window.show();
Task<Void> task = new Task<Void>(){
@Override
protected Void call() {
new VisitPage().Start(this,URLTextField.getText());;
return null;
}
};
buttonStart.setOnAction(new EventHandler<ActionEvent>() {
/*
* Start Button Clicked
*/
public void handle(ActionEvent event) {
new Thread(task).start();
}
});
buttonStop.setOnAction(new EventHandler<ActionEvent>() {
/*
* Start Button Pressed
*/
public void handle(ActionEvent event) {
System.out.println("Stop Pressed");
}
});
}
public class VisitPage {
private String URL;
Browser BrowserFactory;
ThreadLocal<WebDriver> drivers;
WebDriver Browser;
public void Start(Task<Void> task, String URL) {
while (true) {
if (task.isCancelled())
{
System.out.println("Canceling...");
System.out.println("Stop Pressed");
Browser.close();
Browser.quit();
BrowserFactory.CloseDriver(drivers);
task.cancel();
}
else
{
/*
* Create Browser Factor to make ThreadLocal Browsers
*/
BrowserFactory = new Browser(1, 1);
drivers = BrowserFactory.SpawnBrowser();
/*
* Grab a Browser
*/
Browser = BrowserFactory.SpawnDriver(drivers);
/*
* Visit and scrape
*/
Browser.get(URL);
/*
* Wait 5 Seconds before closing
*/
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Browser.close();
Browser.quit();
BrowserFactory.CloseDriver(drivers);
}
}
}
}
public static void main(String[] args) {
launch(args);
}
}
根据文件
与FutureTask一样,Task是单发类,不能重用。 请参阅服务以获取可重复使用的工作人员。
因此,您必须为每次运行创建新任务。 因此,我在Main中将任务添加为字段:
Stage window;
GridPane grid;
Task<Void> task;
然后,在单击开始按钮时创建任务:
buttonStart.setOnAction(new EventHandler<ActionEvent>() {
/*
* Start Button Clicked
*/
@Override
public void handle(ActionEvent event) {
if(task != null) {
System.out.println("Task already running");
return;
}
task = new Task<Void>() {
@Override
protected Void call() {
new VisitPage().start(this, URLTextField.getText());
;
return null;
}
};
Thread thread = new Thread(task);
thread.setDaemon(true);
thread.start();
}
});
在停止按钮上单击,您必须取消任务:
buttonStop.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) {
if(task == null) {
System.out.println("Task not running");
return;
}
System.out.println("Stop Pressed");
task.cancel();
task = null;
}
});
这将无济于事,因为取消任务是您的责任,而您并没有结束无限循环。 因此,您的VisitPage应该如下所示(我跳过了测试详细信息,因为我没有在类路径上使用它们):
public class VisitPage {
public void start(Task<Void> task, String URL) {
while (!task.isCancelled()) {
System.out.println("Running test");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Test run ended");
}
System.out.println("Canceling...");
System.out.println("Stop Pressed");
return;
}
}
一些小要点:
从技术task.cancel()
如果您不捕获线程正在睡眠时引发的InterruptedException
,则task.cancel()
有时会终止线程。
我不确定您的代码是如何编译的,但是我必须使某些变量最终化,以便可以在处理程序中使用它们:(没关系,从Java SE 8开始,局部变量可以有效地最终化)
final TextField URLTextField = new TextField();
//...
final Task<Void> task = new Task<Void>(){
//...
我会将创建的线程定义为守护程序,这样当您关闭UI而不停止测试时它将不会继续运行:
Thread thread = new Thread(task);
thread.setDaemon(true);
thread.start();
我还重命名了Start
方法来start
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.