Home Constantly Updating JavaFX GUI
Reply: 3

Constantly Updating JavaFX GUI

Shane Miller
1#
Shane Miller Published in 2017-12-07 22:28:21Z

I'm currently working on a project where I convert the time into base 10 time (essentially it will end up displaying a percentage of the day that has passed. ex: 12:00 noon would be displayed as 50.00 in base 10 time). Currently, I know my algorithm is correct since it prints out correctly if I print it to the console, but for some reason, I can't get my GUI to display. If I get rid of the part where I attempt to constantly update the GUI to display the correct numbers, the GUI displays fine, but with no numbers. My code is as follows:

package ClockPackage;

import java.util.Calendar;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import javafx.scene.text.Text;
import javafx.stage.Stage;

public class ClockView extends Application {
    Pane background;
    static Text firstDigit;
    static Text secondDigit;
    static Text thirdDigit;
    static Text fourthDigit;
    Text middleDecimal;

    /* Sets the first digit of the base 10 time to the passed through char. */
    static void setFirstDigit(char x1) {
        String digitString = "";
        digitString += x1;
        firstDigit.setText(digitString);
    }

    /* Sets the second digit of the base 10 time to the passed through char. */
    static void setSecondDigit(char x2) {
        String digitString = "";
        digitString += x2;
        secondDigit.setText(digitString);
    }

    /* Sets the third digit of the base 10 time to the passed through char. */
    static void setThirdDigit(char y1) {
        String digitString = "";
        digitString += y1;
        thirdDigit.setText(digitString);
    }

    /* Sets the fourth digit of the base 10 time to the passed through char. */
    static void setFourthDigit(char y2) {
        String digitString = "";
        digitString += y2;
        fourthDigit.setText(digitString);
    }

    /* Main Method that Launches the GUI */
    public static void main(String[] args) {
        Application.launch(args);

    }

    @Override
    public void start(Stage primaryStage) throws Exception {
            final double TEXTFIELD_LAYOUT_Y = 200;

            //Background Pane
            background = new Pane();

            //First digit textField
            firstDigit = new Text();
            firstDigit.setLayoutX(17);
            firstDigit.setLayoutY(TEXTFIELD_LAYOUT_Y);
            firstDigit.setStyle("-fx-font-size: 96pt;");

            //Second digit textField
            secondDigit = new Text();
            secondDigit.setLayoutX(117);
            secondDigit.setLayoutY(TEXTFIELD_LAYOUT_Y);
            secondDigit.setStyle("-fx-font-size: 96pt;");

            //Middle decimal
            middleDecimal = new Text(".");
            middleDecimal.setLayoutX(219);
            middleDecimal.setLayoutY(210);
            middleDecimal.setStyle("-fx-font-size: 72pt;");

            //Third digit textField
            thirdDigit = new Text();
            thirdDigit.setLayoutX(250);
            thirdDigit.setLayoutY(TEXTFIELD_LAYOUT_Y);
            thirdDigit.setStyle("-fx-font-size: 96pt;");

            //Fourth digit textField
            fourthDigit = new Text();
            fourthDigit.setLayoutX(362);
            fourthDigit.setLayoutY(TEXTFIELD_LAYOUT_Y);
            fourthDigit.setStyle("-fx-font-size: 96pt;");

            /* Adding the Nodes to the Pane */
            background.getChildren().addAll(firstDigit, secondDigit, middleDecimal, thirdDigit, fourthDigit);

            /* Setting the Scene */
            Scene scene = new Scene(background, 470, 258);
            primaryStage.setTitle("Base 10 Clock");
            primaryStage.setScene(scene);
            primaryStage.show();

            /*
             * Calculates the time in base 10 time and calls the 4 methods
             * to set the GUI display.
             * 
             * In a constant while loop in order to continuously update
             * the GUI.
             */
            Calendar now;
            double currentTime;
            String timeString;
            long timestamp;
            while(true) {
                /* Sleep for 8.64 seconds since that is how long it is between
                increments of 0.01 in base 10 time. */
                Thread.sleep(8640);
                now = Calendar.getInstance();
                timestamp = now.get(Calendar.HOUR_OF_DAY)*60*60 + now.get(Calendar.MINUTE)*60 + now.get(Calendar.SECOND);
                currentTime = timestamp/86400.0;
                timeString = "" + currentTime;
                setFirstDigit(timeString.charAt(2));
                setSecondDigit(timeString.charAt(3));
                setThirdDigit(timeString.charAt(4));
                setFourthDigit(timeString.charAt(5));
            }
    }
}

Does anyone have any idea how I would go about making the GUI both show up and update the numbers constantly? I can't figure out how to get it to do both. I've seen where people use buttons to update data, but I haven't seen where the display is constantly automatically updated.

Thanks!

Michael McKay
2#
Michael McKay Reply to 2017-12-08 14:30:02Z

Here is a working version.

import java.util.Calendar;
import java.util.Timer;
import java.util.TimerTask;

import javafx.application.Application;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import javafx.scene.text.Text;
import javafx.stage.Stage;

public class ClockView extends Application {
    Pane background;
    static Text firstDigit;
    static Text secondDigit;
    static Text thirdDigit;
    static Text fourthDigit;
    Text middleDecimal;

    public final Timer clockTimer = new Timer();


    /* Sets the first digit of the base 10 time to the passed through char. */
    static void setFirstDigit(char x1) {
        String digitString = "";
        digitString += x1;
        firstDigit.setText(digitString);
    }

    /* Sets the second digit of the base 10 time to the passed through char. */
    static void setSecondDigit(char x2) {
        String digitString = "";
        digitString += x2;
        secondDigit.setText(digitString);
    }

    /* Sets the third digit of the base 10 time to the passed through char. */
    static void setThirdDigit(char y1) {
        String digitString = "";
        digitString += y1;
        thirdDigit.setText(digitString);
    }

    /* Sets the fourth digit of the base 10 time to the passed through char. */
    static void setFourthDigit(char y2) {
        String digitString = "";
        digitString += y2;
        fourthDigit.setText(digitString);
    }

    /* Main Method that Launches the GUI */
    public static void main(String[] args) {
        launch(args);
    }


    @Override
    public void start(Stage primaryStage) throws Exception {
        final double TEXTFIELD_LAYOUT_Y = 200;

        //Background Pane
        background = new Pane();

        //First digit textField
        firstDigit = new Text("0");
        firstDigit.setLayoutX(17);
        firstDigit.setLayoutY(TEXTFIELD_LAYOUT_Y);
        firstDigit.setStyle("-fx-font-size: 96pt;");

        //Second digit textField
        secondDigit = new Text("0");
        secondDigit.setLayoutX(117);
        secondDigit.setLayoutY(TEXTFIELD_LAYOUT_Y);
        secondDigit.setStyle("-fx-font-size: 96pt;");

        //Middle decimal
        middleDecimal = new Text(".");
        middleDecimal.setLayoutX(219);
        middleDecimal.setLayoutY(210);
        middleDecimal.setStyle("-fx-font-size: 72pt;");

        //Third digit textField
        thirdDigit = new Text("0");
        thirdDigit.setLayoutX(250);
        thirdDigit.setLayoutY(TEXTFIELD_LAYOUT_Y);
        thirdDigit.setStyle("-fx-font-size: 96pt;");

        //Fourth digit textField
        fourthDigit = new Text("0");
        fourthDigit.setLayoutX(362);
        fourthDigit.setLayoutY(TEXTFIELD_LAYOUT_Y);
        fourthDigit.setStyle("-fx-font-size: 96pt;");

        /* Adding the Nodes to the Pane */
        background.getChildren().addAll(firstDigit, secondDigit, middleDecimal, thirdDigit, fourthDigit);

        /* Setting the Scene */
        Scene scene = new Scene(new Group(), 470, 258);
        Group root = (Group)scene.getRoot();
        root.getChildren().add(background);
        primaryStage.setTitle("Base 10 Clock");
        primaryStage.setScene(scene);
        primaryStage.show();

        clockTimer.scheduleAtFixedRate(new TimerTask() {

                Calendar now;
                double currentTime;
                String timeString;
                long timestamp;

                @Override
                public void run() { 
                    /*
                     * Calculates the time in base 10 time and calls the 4 methods
                     * to set the GUI display.
                     * 
                     * In a constant while loop in order to continuously update
                     * the GUI.
                     */
                    now = Calendar.getInstance();
                    timestamp = now.get(Calendar.HOUR_OF_DAY)*60*60 + now.get(Calendar.MINUTE)*60 + now.get(Calendar.SECOND);
                    currentTime = timestamp/86400.0;
                    timeString = "" + currentTime;
                    Platform.runLater(new Runnable() {
                        @Override  public void run() {
                            setFirstDigit(timeString.charAt(2));
                            setSecondDigit(timeString.charAt(3));
                            setThirdDigit(timeString.charAt(4));
                            setFourthDigit(timeString.charAt(5));
                        }
                    });
                }
            }, 0, 8640  // Sleep for 8.64 seconds since that is how long it is between
        );              // increments of 0.01 in base 10 time.
    }
}
Sedrick
3#
Sedrick Reply to 2017-12-07 22:46:12Z

Replace:

    Calendar now;
    double currentTime;
    String timeString;
    long timestamp;
    while (true)
    {
        /* Sleep for 8.64 seconds since that is how long it is between
            increments of 0.01 in base 10 time. */
        Thread.sleep(8640);
        now = Calendar.getInstance();
        timestamp = now.get(Calendar.HOUR_OF_DAY) * 60 * 60 + now.get(Calendar.MINUTE) * 60 + now.get(Calendar.SECOND);
        currentTime = timestamp / 86400.0;
        timeString = "" + currentTime;
        setFirstDigit(timeString.charAt(2));
        setSecondDigit(timeString.charAt(3));
        setThirdDigit(timeString.charAt(4));
        setFourthDigit(timeString.charAt(5));
    }

with:

        Timeline overEightSeconsWonder = new Timeline(new KeyFrame(Duration.seconds(8.64), (ActionEvent event) ->
        {
            Calendar now = Calendar.getInstance();
            long timestamp = now.get(Calendar.HOUR_OF_DAY) * 60 * 60 + now.get(Calendar.MINUTE) * 60 + now.get(Calendar.SECOND);
            double currentTime = timestamp / 86400.0;
            String timeString = "" + currentTime;
            setFirstDigit(timeString.charAt(2));
            setSecondDigit(timeString.charAt(3));
            setThirdDigit(timeString.charAt(4));
            setFourthDigit(timeString.charAt(5));
        }));
        overEightSeconsWonder.setCycleCount(Timeline.INDEFINITE);
        overEightSeconsWonder.play();
Tim
4#
Tim Reply to 2017-12-07 22:53:17Z

You should replace the while(true) loop with a new thread or a service call with another thread. The main thread is already responsible for updating the UI, so when you have some kind of blocking (IO, loops that take a long time, etc...), it will prevent the UI thread from updating.

Link to the Service interface

Create a service:

public static class TimeService extends Service<String> {

    protected Task createTask() {
        return new Task<String>() {
            protected String call() throws Exception {
                // TODO: Do work - return the date/time as a String
                // If you need a Thread.sleep, use a spawn a new thread
            }
        };
    }
}

Then in your controller:

TimeService timeService = new TimeService();
timeService.restart();

You could also do all sorts of things like binding UI elements to properties in the TimeService (that way the UI will "just update" as the service is running).

You need to login account before you can post.

About| Privacy statement| Terms of Service| Advertising| Contact us| Help| Sitemap|
Processed in 0.317197 second(s) , Gzip On .

© 2016 Powered by mzan.com design MATCHINFO