Dess
Dess

Reputation: 435

JavaFx how to check time every 1 hour

I'm trying to write a simple JavaFx program, which suppose to check time and every full hour do something(at first only change the text in label). But I have a problem with constantly checking the time. I'm using a Calendar class. If I write a while(true) loop, the program starts but doesn't do anything. Should I use threads? I know it's probably trivial issue, but I can't figure it out, I'm kind of new in this;p

Thanks guys for help(I didn't know whether I should reply below or edit this post). I managed to create my own version, which I based on link, you gave me.

public class Trening extends Application {
@Override
public void start(Stage primaryStage) {
    Task<Integer> task = new Task<Integer>() {
        @Override
        protected Integer call() throws Exception {
            Calendar tajm = Calendar.getInstance();
            int hour = tajm.get(Calendar.HOUR_OF_DAY);
            int minutes = 0;
            updateMessage(Integer.toString(hour));
            while (true) {
                try {
                    minutes = 60 - tajm.get(Calendar.MINUTE);
                    Thread.sleep(minutes * 60000);
                    if (tajm.get(Calendar.HOUR_OF_DAY) != hour) {
                        hour = tajm.get(Calendar.HOUR_OF_DAY);
                        updateMessage(Integer.toString(hour));

                    } else {

                    }
                } catch (InterruptedException ie) {
                    //System.err.print("...");
                }
            }
        }
    };

    Label btn = new Label();
    btn.textProperty().bind(task.messageProperty());
    new Thread(task).start();

    StackPane root = new StackPane();
    root.getChildren().add(btn);

    Scene scene = new Scene(root, 300, 250);

    primaryStage.setTitle("...");
    primaryStage.setScene(scene);
    primaryStage.show();
}

/**
 * The main() method is ignored in correctly deployed JavaFX application.
 * main() serves only as fallback in case the application can not be
 * launched through deployment artifacts, e.g., in IDEs with limited FX
 * support. NetBeans ignores main().
 *
 * @param args the command line arguments
 */
public static void main(String[] args) {
    launch(args);
}}

Like I said I'm rather new to programming, so I appreciate every piece of advice. Thank you very much for your help, and if you have any more advice to what I have written, I wouldn't mind;p

And sorry I didn't marked your answers as useful, but I have too low reputation...

Upvotes: 0

Views: 1200

Answers (2)

Sindri J&#243;elsson
Sindri J&#243;elsson

Reputation: 369

This should get you started, do note I used a Service. A Task would probably better for this. It's been a while since I wrote Java but by following this guide I was able to quickly create the sample below.

It also uses the Calendar library, I hope you find it useful.

import javafx.application.*;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import javafx.concurrent.Service;
import javafx.concurrent.Task;
import javafx.concurrent.WorkerStateEvent;
import javafx.event.EventHandler;


import java.util.Calendar;
import java.util.Date;



public class StackOverflow_001 <T extends Comparable<T>> extends Application {


    public static void main(String[] args) {
        launch(args); // Launches the application
    }

            // A simple service with an internal clock.
    private static class HourService extends Service<Date>
    {

        private Calendar calendar;

        public final void setCalendarInstance(Calendar c)
        {
            calendar = c;
        }


        @Override
        protected Task<Date> createTask() {

            return new Task<Date>() {

                protected Date call()
                {
                    int secondsdelay = 5;
                    Date timeStarted = calendar.getTime();
                    Date timeEnd = new Date(timeStarted.getTime() + 1000 * secondsdelay );//* 60 * 60);

                    while( timeEnd.after(calendar.getTime()) )
                    {
                        try {
                            System.out.println("---");
                            System.out.println("Time: " + calendar.getTime());
                            System.out.println("End:  " +timeEnd);

                            Thread.sleep(500);
                            calendar = Calendar.getInstance();
                        } catch (InterruptedException e) {

                            if (isCancelled()) {
                                updateMessage("Cancelled");
                                break;
                            }
                        }
                    }
                    System.out.println("Service ended.");
                    return timeEnd;

                }
            };
        }


    }

            // Sets up everything and creates the window.
    @Override
    public void start(Stage primaryStage) throws Exception {

        final VBox root = new VBox();
        primaryStage.setScene(new Scene(root, 800, 600));

        final Button btn1 = new Button();
        btn1.setText(Calendar.getInstance().getTime().toString());

        root.getChildren().add(btn1);

        final HourService hservice = new HourService();
        hservice.setCalendarInstance(Calendar.getInstance());
        hservice.setOnSucceeded(new EventHandler<WorkerStateEvent>() { // Anonymous

            @Override
            public void handle(WorkerStateEvent t) {
                btn1.setText(Calendar.getInstance().getTime().toString());
                hservice.restart();
            }
        });

        hservice.start();

        primaryStage.show();

    }


}

Upvotes: 0

Katona
Katona

Reputation: 4901

This is one approach.

First, encapsulate your periodic task.

public static class MyPeriodicTask implements Runnable {

    public void run() {
        boolean fullHour = ... // determine somehow
        if (fullHour) {
            Platform.runLater(new Runnable() {

                public void run() {
                    // Modify label here
                }
            });
        }
    }
}

Note the Platform.runLater() call, this quarantees that passed Runnable will be executed by the JavaFX application thread, where you can safely interact with the GUI.

Then use the an ExecutorService to run your task periodically

ScheduledExecutorService executorService = Executors.newScheduledThreadPool(1);
executorService.scheduleAtFixedRate(new MyPeriodicTask(), 1, 1, TimeUnit.MINUTES);

This will run your task in every minute (after 1 minute initial delay).

But if you are serious about JavaFX, then I think you should read Concurrency in JavaFX at least.

Upvotes: 3

Related Questions