-1

I'm pretty new to Java programming, but I want to make a simple Up or Down counter (based on input values). I've created an FXML application for my code, and I want the counter to update. Let's say I want to count up from 1 to 6, I want the application to show 1, 2, 3, 4, 5, 6. I've managed to do it in the console, but the FXML application seems to pause while it's counting.

Can someone help me with this? Below is all my code:

UpOrDownCounter.java

package upOrDownCounter;

public class UpOrDownCounter {

private int stop;
private int start;
private int counter = 0;

public UpOrDownCounter(int start, int stop){
    this.stop = stop;
    this.start = start;

    if(start > stop) {
        counter = start + 1;
    }else {
        counter = start - 1;
    }

    if(start == stop) {
        throw new IllegalArgumentException("Start and stop cannot be the same value");
    }
}

int getCounter() {
    return counter;
}

boolean count() {
    if(start > stop) {
        if(getCounter() != stop) {
            counter = counter - 1;
            return true;
        }
    }else {
        if(getCounter() != stop) {
            counter = counter + 1;
            return true;
        }
    }
    return false;
}

public static void main(String[] args) {
    UpOrDownCounter cd = new UpOrDownCounter(6, 6);
    System.out.println(cd.getCounter());
    System.out.println(cd.count());
    System.out.println(cd.getCounter());
    System.out.println(cd.count());
    System.out.println(cd.getCounter());
    System.out.println(cd.count());
    System.out.println(cd.getCounter());
    System.out.println(cd.count());
    System.out.println(cd.getCounter());
    System.out.println(cd.count());
    System.out.println(cd.getCounter());
    System.out.println(cd.count());
    System.out.println(cd.getCounter());
    System.out.println(cd.count());
  }
}

UpOrDownCounterController.java

package upOrDownCounter;

import javafx.fxml.FXML;
import javafx.scene.control.TextField;

public class UpOrDownCounterController {
UpOrDownCounter cd;

@FXML TextField startValue;
@FXML TextField stopValue;
@FXML TextField counterOutput;

@FXML
void handleClick() {
    String startString = startValue.getText();
    int start = Integer.valueOf(startString);
    String stopString = stopValue.getText();
    int stop = Integer.valueOf(stopString);

    cd = new UpOrDownCounter(start, stop);

    while(cd.count()) {
        try {
            System.out.println("Counter: " + String.valueOf(cd.getCounter()));
            counterOutput.setText(String.valueOf(cd.getCounter()));
            System.out.println(String.valueOf(cd.getCounter()));
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
      }
   }
}

UpOrDownCounter.fxml

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.control.Button?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.VBox?>


<VBox xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/9" fx:controller="upOrDownCounter.UpOrDownCounterController">
 <children>
  <TextField fx:id="startValue" promptText="Start" />
  <TextField fx:id="stopValue" promptText="Stop" />
  <Button onAction="#handleClick" mnemonicParsing="false" prefHeight="37.0" prefWidth="196.0" text="Start countdown" />
  <TextField fx:id="counterOutput" prefHeight="32.0" prefWidth="196.0" />
 </children>
</VBox>
SedJ601
  • 12,173
  • 3
  • 41
  • 59
  • You `Main` does not appear to be in the correct `JavaFX` format or maybe that's the code you used before trying to make a `JavaFx` app? – SedJ601 Jan 16 '18 at 15:09
  • 1
    Don't block the FX Application Thread with `Thread.sleep()` (you will prevent the UI from being rendered). See, for example, https://stackoverflow.com/questions/9966136/javafx-periodic-background-task – James_D Jan 16 '18 at 15:11
  • If you are using `UpOrDownCounter.java` in your `JavaFX` project, it should not have that `main` method in it. – SedJ601 Jan 16 '18 at 15:17
  • 1
    You should clarify your question! You're not starting a JavaFX application the way it needs to start or you didn't provide all the code. So, I'm downgrading your question. If you really need help with a JavaFX application thread, you first need to start it. Well, to start a JavaFX application, take a look here: https://docs.oracle.com/javase/8/javafx/get-started-tutorial/hello_world.htm and then, if you edit your question, I can dimiss the downgrade vote. BTW you don't need to get a so complex logic to build an *Up or Down* counter. – R. Karlus Jan 16 '18 at 15:30

1 Answers1

0

You are going to have to play with your code a little but here is how you solve your first problem. Use Timeline. Altered answer using this code.

    //Duration.seconds(1) tells this Timeline to run every second
    Timeline oneSecondsWonder = new Timeline(new KeyFrame(Duration.seconds(1), new EventHandler<ActionEvent>()
    {

        @Override
        public void handle(ActionEvent event)
        {
            System.out.println("Counter: " + String.valueOf(cd.getCounter()));
            counterOutput.setText(String.valueOf(cd.getCounter()));
            System.out.println(String.valueOf(cd.getCounter()));
            cd.count();
        }
    }));

    oneSecondsWonder.setCycleCount(start - stop);//This tells the TimeLine to repeat itself a certain number of times.
    oneSecondsWonder.play();//This starts the Timeline.

Full Code

package upOrDownCounter;

import javafx.fxml.FXML;
import javafx.scene.control.TextField;

public class UpOrDownCounterController {
    UpOrDownCounter cd;

    @FXML
    TextField startValue;
    @FXML
    TextField stopValue;
    @FXML
    TextField counterOutput;

    @Override
    public void initialize(URL location, ResourceBundle resources)
    {

    }

    @FXML
    void handleClick()
    {
        String startString = startValue.getText();
        int start = Integer.valueOf(startString);
        String stopString = stopValue.getText();
        int stop = Integer.valueOf(stopString);

        cd = new UpOrDownCounter(start, stop);

        Timeline oneSecondsWonder = new Timeline(new KeyFrame(Duration.seconds(1), new EventHandler<ActionEvent>()
        {

            @Override
            public void handle(ActionEvent event)
            {
                System.out.println("Counter: " + String.valueOf(cd.getCounter()));
                counterOutput.setText(String.valueOf(cd.getCounter()));
                System.out.println(String.valueOf(cd.getCounter()));
                cd.count();
                if (cd.getCounter() == stop) {

                }
            }
        }));

        oneSecondsWonder.setCycleCount(start - stop);
        oneSecondsWonder.play();
    }
}
SedJ601
  • 12,173
  • 3
  • 41
  • 59