我正在制作一个简单的JavaFX大学课程项目,我需要一种处理线程的好方法,主要是在激活某个标志时运行它们。
这是我提出的简单草图:
public class ListenerService extends Thread {
private static ArrayList<ListenerService> listeners = new ArrayList<>();
private ToggleButton button;
private File folder;
private SimpleBooleanProperty active = new SimpleBooleanProperty();
ListenerService(ToggleButton button, String pathname) {
this.button = button;
this.folder = new File(pathname);
button.setOnAction(event -> active.set(button.isSelected()));
active.addListener((ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue)
-> {if (newValue.booleanValue()) start();});
listeners.add(this);
}
@Override
public void run() {
while(active.get())
System.out.print(".");
}
流程如下:
用户在表单上动态创建ToggleButton。一个 创建ListenerService对象,其中包含一个按钮和一个目录 被分配。
为按钮分配了一个监听器 - 如果它被点击 - 激活 国旗。否则,停用。这里的旗帜是 SimpleBooleanProperty实例。
一旦我运行该程序,它就冻结了。我试着让旗帜变得不稳定,但没有改变。由于标志是从外部控制的(从GUI),因此无法使此方法同步。
我做错了什么?
答案 0 :(得分:0)
您基本上创建了一个新的线程,只要选择了该按钮就会运行,并在未选择该按钮时退出。
import javafx.application.Application;
import static javafx.application.Application.launch;
import javafx.scene.Scene;
import javafx.scene.control.ToggleButton;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
public class ThreadApp extends Application {
public class Worker implements Runnable{
private boolean active;
public void setActive(boolean active) {
this.active = active;
}
@Override
public void run() {
while(active)
{
System.out.println("Active! " + System.currentTimeMillis());
}
}
}
public class WorkerToggle extends ToggleButton {
Worker worker;
public WorkerToggle(String text) {
super(text);
this.worker = new Worker();
setOnAction((event) -> {
if(isSelected())
{
worker.setActive(true);
Thread thread = new Thread(worker);
thread.setDaemon(true);
thread.start();
}else
{
worker.setActive(false);
}
});
}
}
@Override
public void start(Stage primaryStage) {
BorderPane rootPane = new BorderPane();
Scene scene = new Scene(rootPane);
rootPane.setCenter(new WorkerToggle("toggle me"));
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
这应该可以正常工作,但是创建线程可能很昂贵,所以如果你发现某些性能问题,你可能需要调查ThreadPoolExecutor
。
答案 1 :(得分:0)
在JavaFX中,您可以使用计划的服务来运行主FX线程。这是一个可能有用的简单示例。
public class JavaFXApplication3 extends Application {
@Override
public void start(Stage primaryStage) throws Exception {
PollingService service = new PollingService();
service.setPeriod(Duration.millis(1000)); // sysout every second
ToggleButton tb = new ToggleButton("Start Process");
tb.setOnAction(event -> {
System.out.println(tb.isSelected());
if(tb.isSelected()){
service.reset();
service.start();
}else {
service.cancel();
}
});
VBox vbox = new VBox(tb);
Scene scene = new Scene(vbox);
primaryStage.setScene(scene);
primaryStage.show();;
}
private class PollingService extends ScheduledService<Void> {
@Override
protected Task<Void> createTask() {
return new Task<Void>() {
@Override
protected Void call() {
System.out.print(".#.");
return null;
}
};
}
}
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
launch(args);
}
}