JavaFX:如何将 Button 属性绑定到线程状态?



我有一个javafx应用程序,它在单击按钮时启动一个新线程。

下面是启动线程的方法:

private void startTest() {
String[] args = {};
String threadId = TestRunner.class.getSimpleName();
mainApp.setRunner(new Thread(() -> {
try {
TestRunner.main(args);
} catch (Throwable e) {
LOGGER.fatal(e.getMessage(), e);
}
}, threadId));
mainApp.getRunner().start();
}

我可以使用setRunner()getRunner()访问器从主应用程序中获取和设置Thread对象。

这是当前发生的情况:

  • 我启动应用程序
  • 我点击按钮[START]
  • 单击后,将启动一个新线程,我将[START]按钮的文本更改为[PAUSE]
  • 我知道线程将在某个时间点完成(当任务完成时(

    我想要实现的:

  • 我想将现在[PAUSE]按钮的文本更改为线程完成后/线程死亡时[START]
  • 其他一些取决于线程状态 的事情我该怎么做?

    我目前正在玩可观察的布尔值,但我可以使用一些帮助来实现这一点。

    提前感谢!

  • 使用Service在主应用中管理后台线程(或当前管理runner属性的任何位置(。像这样:

    public class MainApp {
    private final Service<Void> testService = new Service<Void>() {
    @Override
    protected Task<Void> createTask() {
    return new Task<Void>() {
    @Override
    protected Void call() throws Exception {
    // code to execute on background thread here:
    while (! isCancelled() ) {
    // ...
    }
    }
    }
    }
    };
    public Service<Void> getTestService() {
    return testService();
    }
    // ...
    }
    

    然后在您的UI中,您需要做的就是

    Button startButton = new Button();
    startButton.textProperty().bind(Bindings.
    when(mainApp.getTestService().runningProperty()).
    then("Pause").
    otherwise("Start"));
    startButton.setOnAction(e -> {
    if (mainApp.getTestService().isRunning()) {
    mainApp.getTestService().cancel();
    } else {
    mainApp.getTestService().restart();
    }
    });
    

    Task文档有大量的信息和示例,说明如何实现从ServicecreateTask()方法返回的Task

    更改节点内部线程的值:

    你有两个选择来做你想做的事情,你可以使用任务类和绑定你的按钮与你的任务值的变化,你有updateMessage("(和updateValue((或updateTitle,或者你可以在你的线程中使用平台类。

    Button StartButton=new Button("Start");
    Thread TestThread=new Thread(new Runnable(){
    @Override
    public void run()
    {
    Platform.runLater(new Runnable(){
    @Override
    public void run()
    {
    StartButton.setText("Pause");    
    
    }
    while(true)
    {
    }
    
    }
    );
    StartButton.addEventHandler(event->{
    if(StartButton.getText().equals("Start"))
    {
    StartThread.start();
    }else{
    StartThread.interrupt();  
    }