【问题标题】:JavaFX 8 - Creating counter with new Thread have secondary effectsJavaFX 8 - 使用新线程创建计数器具有次要效果
【发布时间】:2018-05-07 22:10:53
【问题描述】:

我想创建一个在每一秒过去后递减的计数器,但是当我运行代码时,有时会在 TextField 中显示正确的值,有时会重复它,或者 NetBeans 控制台会出现一些奇怪的错误。

谁能帮我解决这个问题? 我只是对代码进行了几处更改,但没有成功。

代码如下:

package javafx_contador;

import javafx.application.Application;
import javafx.application.Platform;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import javafx.scene.control.TextField;
import javafx.scene.text.Font;
import javafx.scene.text.FontWeight;
import javafx.stage.Stage;
import javafx.stage.WindowEvent;
import javafx.geometry.Pos;
import java.util.logging.Level;
import java.util.logging.Logger;

public class JavaFX_Contador extends Application
{
  TextField tf;
  Thread1 contador;

  @Override
  public void start(Stage stage)
  {
    tf = new TextField();
    tf.setEditable(false);
    tf.setMaxWidth(100);
    tf.setAlignment(Pos.CENTER);
    tf.setLayoutX(160);
    tf.setLayoutY(140);
    tf.setFont(Font.font("Cambria", FontWeight.BOLD, 20));

    Pane pane = new Pane();
    pane.setStyle("-fx-background: green;");
    pane.getChildren().add(tf);

    Scene scene = new Scene(pane, 400, 300);

    stage.setResizable(false);
    stage.setTitle("JavaFX (Contador)");
    stage.setScene(scene);
    stage.show();

    pane.requestFocus();

    stage.setOnCloseRequest((WindowEvent we) ->
    {
      System.out.println("A Aplicação vai encerrar.");
      Platform.exit();
      System.exit(0);
    });

    contador = new Thread1();
    contador.start();
  }


  public class Thread1 extends Thread
  {
    int tempo = 60;

    @Override
    public void run()
    {
      tf.setText(Integer.toString(tempo));
      while (tempo > 0)
      {
        try
        {
          Thread1.sleep(1000);
        }
        catch (InterruptedException ex)
        {
          Logger.getLogger(JavaFX_Contador.class.getName()).log(Level.SEVERE, null, ex);
        }
        tempo--;
        tf.setText(Integer.toString(tempo));
      }
      System.out.println("Terminou o tempo!");
    }
  }


  public static void main(String[] args)
  {
    launch(args);
  }
}

我在没有“Thread.Sleep”的情况下编写了代码,而是使用了“PauseTransition”,但有一个问题,即使在消息“Terminou o tempo!”之后,计数器也会停止在 -1。出现在控制台中。 我有“while (tempo > 0)”所以我不明白为什么它在达到值 0 时不会停止。

package javafx_contador;

import javafx.application.Application;
import javafx.application.Platform;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import javafx.scene.control.TextField;
import javafx.scene.text.Font;
import javafx.scene.text.FontWeight;
import javafx.stage.Stage;
import javafx.stage.WindowEvent;
import javafx.geometry.Pos;
import javafx.animation.PauseTransition;
import javafx.util.Duration;

public class JavaFX_Contador extends Application
{
  int tempo = 60;
  TextField tf;
  Thread1 contador;

  @Override
  public void start(Stage stage)
  {
    tf = new TextField(Integer.toString(tempo));
    tf.setEditable(false);
    tf.setMaxWidth(100);
    tf.setAlignment(Pos.CENTER);
    tf.setLayoutX(160);
    tf.setLayoutY(140);
    tf.setFont(Font.font("Cambria", FontWeight.BOLD, 20));

    Pane pane = new Pane();
    pane.setStyle("-fx-background: green;");
    pane.getChildren().add(tf);

    Scene scene = new Scene(pane, 400, 300);

    stage.setResizable(false);
    stage.setTitle("JavaFX (Contador)");
    stage.setScene(scene);
    stage.show();

    pane.requestFocus();

    stage.setOnCloseRequest((WindowEvent we) ->
    {
      System.out.println("A Aplicação vai encerrar.");
      Platform.exit();
      System.exit(0);
    });

    contador = new Thread1();
    contador.start();
  }


  public class Thread1 extends Thread
  {
    @Override
    public void run()
    {
      PauseTransition pausa = new PauseTransition(Duration.millis(1000));

      pausa.setOnFinished(e ->
      {
        tempo--;
        tf.setText(Integer.toString(tempo));
      });

      while (tempo > 0)
        pausa.play();

      System.out.println("Terminou o tempo!");
    }
  }


  public static void main(String[] args)
  {
    launch(args);
  }
}

【问题讨论】:

标签: java multithreading javafx javafx-8


【解决方案1】:

不要阻塞 JavaFx 应用程序线程使用Thread.Sleep();,因此使用javafx.concurrent.Taskjavafx.animation.PauseTransition 来实现您的目标

例如:

    Task task = new Task() {
        @Override
        public Void call() {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return null;
        }
    };

    task.setOnSucceeded((e) -> {
        //
       // YOUR UI CHANGES GOES HERE 
      //
    });
    new Thread(task).start(); 

--------------------或--------

 PauseTransition pause = new PauseTransition(Duration.millis(1000));
    pause.setOnFinished(e -> {
        //
       // YOUR UI CHANGES GOES HERE 
      //
    });
    pause.play();

【讨论】:

  • 我尝试了 PauseTransition 而不是 Thread.Sleep,但我仍然有问题。计数器在达到 -1 时停止,而不是在达到 0 时停止。我不明白为什么会发生这种情况。
【解决方案2】:

您可以像这样使用 Platform.runLater 来避免阻塞主 UI 线程

Platform.runLater(new Runnable() {
            @Override
public void run() {
 tf.setText(Integer.toString(tempo));
this.sleep(1000);
}

【讨论】:

  • 我试图在代码上实现 Platform.runLater 但我无法让它运行!你能告诉我怎么做吗?
  • 如何避免阻塞 FX 应用程序线程?您正在明确在 FX 应用程序线程上调用 Thread.sleep(...)
  • Platform.runLater 就像 android 的循环器,您可以从任何将其放入事件队列的方法调用它,并在调用时执行更多详细信息here
猜你喜欢
  • 2015-10-26
  • 2013-04-08
  • 2021-09-25
  • 1970-01-01
  • 2022-01-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-04-18
相关资源
最近更新 更多