How to update the label box every 2 seconds in java fx?

前端 未结 3 540
故里飘歌
故里飘歌 2020-11-27 19:58

I\'m trying to simulate a basic thermostat in an application GUI.

I want to update a label box value every 2 secs with the new temperature value.

For example

相关标签:
3条回答
  • 2020-11-27 20:22

    Calling Platform.runLater worked for me:

    Platform.runLater(new Runnable() {
    
        @Override
        public void run() {
    
        }
    });
    
    0 讨论(0)
  • 2020-11-27 20:24

    Here is an alternate solution which uses a JavaFX animation Timeline instead of a Timer.

    I like this solution because the animation framework ensures that everything happens on the JavaFX application thread, so you don't need to worry about threading issues.

    temperatureprobe

    import javafx.animation.*;
    import javafx.application.Application;
    import javafx.beans.binding.Bindings;
    import javafx.beans.property.*;
    import javafx.event.*;
    import javafx.scene.*;
    import javafx.scene.control.*;
    import javafx.scene.layout.VBox;
    import javafx.stage.Stage;
    import javafx.util.Duration;
    
    import java.util.Random;
    
    public class ThermostatApp extends Application {
      @Override public void start(final Stage stage) throws Exception {
        final Thermostat       thermostat       = new Thermostat();
        final TemperatureLabel temperatureLabel = new TemperatureLabel(thermostat);
    
        VBox layout = new VBox(10);
        layout.getChildren().addAll(temperatureLabel);
        layout.setStyle("-fx-background-color: cornsilk; -fx-padding: 20; -fx-font-size: 20;");
    
        stage.setScene(new Scene(layout));
        stage.show();
      }
    
      public static void main(String[] args) throws Exception {
        launch(args);
      }
    }
    
    class TemperatureLabel extends Label {
      public TemperatureLabel(final Thermostat thermostat) {
        textProperty().bind(
          Bindings.format(
            "%3d \u00B0F",
            thermostat.temperatureProperty()
          )
        );
      }
    }
    
    class Thermostat {
      private static final Duration PROBE_FREQUENCY = Duration.seconds(2);
    
      private final ReadOnlyIntegerWrapper temperature;
      private final TemperatureProbe       probe;
      private final Timeline               timeline;
    
      public ReadOnlyIntegerProperty temperatureProperty() {
        return temperature.getReadOnlyProperty();
      }
    
      public Thermostat() {
        probe       = new TemperatureProbe();
        temperature = new ReadOnlyIntegerWrapper(probe.readTemperature());
    
        timeline = new Timeline(
            new KeyFrame(
              Duration.ZERO,
              new EventHandler<ActionEvent>() {
                @Override public void handle(ActionEvent actionEvent) {
                  temperature.set(probe.readTemperature());
                }
              }
            ),
            new KeyFrame(
              PROBE_FREQUENCY
            )
        );
        timeline.setCycleCount(Timeline.INDEFINITE);
        timeline.play();
      }
    }
    
    class TemperatureProbe {
      private static final Random random = new Random();
    
      public int readTemperature() {
        return 72 + random.nextInt(6);
      }
    }
    

    The solution is based upon the countdown timer solution from: JavaFX: How to bind two values?

    0 讨论(0)
  • 2020-11-27 20:27

    To solve your task using Timer you need to implement TimerTask with your code and use Timer#scheduleAtFixedRate method to run that code repeatedly:

    Timer timer = new Timer();
        timer.scheduleAtFixedRate(new TimerTask() {
            @Override
            public void run() {
                System.out.print("I would be called every 2 seconds");
            }
        }, 0, 2000);
    

    Also note that calling any UI operations must be done on Swing UI thread (or FX UI thread if you are using JavaFX):

    private int i = 0;
    private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
        Timer timer = new Timer();
        timer.scheduleAtFixedRate(new TimerTask() {
            @Override
            public void run() {
                SwingUtilities.invokeLater(new Runnable() {
                    @Override
                    public void run() {
                        jTextField1.setText(Integer.toString(i++));
                    }
                });
            }
        }, 0, 2000);
    }
    

    In case of JavaFX you need to update FX controls on "FX UI thread" instead of Swing one. To achieve that use javafx.application.Platform#runLater method instead of SwingUtilities

    0 讨论(0)
提交回复
热议问题