Reputation: 435
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
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
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