How to make a BarChart behave like a timer?
up vote
0
down vote
favorite
Im trying to build a Quizz Application with JavaFX.
The user is supposed to answer as many questions as possible in one minute. I have created a subclass of BarChart that i want to use to visualise the how much time is left. My class implements Runnable because the timer is supposed to run as its own thread (right?).
I want to set the bargraph to 60, and then decrease the bar for each second. I have tried different ways to do this but none of them are succesful.
Heres what the class look like now:
public class StopWatchBar extends BarChart implements Runnable {
public StopWatchBar() {
super(new CategoryAxis(), new NumberAxis(0, 60, 1));
super.setTitle("Time");
this.setMaxWidth(200);
this.setScaleShape(true);
this.setAnimated(false);
this.setCenterShape(true);
}
@Override
public void run() {
XYChart.Series timeDataSeries = new XYChart.Series();
timeDataSeries.getData().add(new XYChart.Data<String, Integer>("", 60));
this.getData().add(timeDataSeries);
int counterSeconds = 60;
long startTime = System.currentTimeMillis();
long endTime = System.currentTimeMillis() + (counterSeconds * 1000);
long startTimePlusOneSecond = startTime + 1000;
while (startTime < endTime) {
if (startTime == startTimePlusOneSecond) {
timeDataSeries.getData().clear();
timeDataSeries.getData().add(new XYChart.Data<String, Number>("", counterSeconds));
counterSeconds--;
startTimePlusOneSecond += 1000;
}
startTime = System.currentTimeMillis();
}
}
}
I have created an object of the class as an instance object in my Scene in PrimaryStage.
In the same scene i also have a button that i want to use to test to execute the counter:
Like this:
timerTestButton.setOnAction(actionEvent -> {
Thread timeBarRunner = new Thread(timeBar);
timeBarRunner.start();
});
When i push the button in the UI i get the Exception:
Exception in thread "Thread-4" java.lang.IllegalStateException: Not on FX application thread; currentThread = Thread-4
at com.sun.javafx.tk.Toolkit.checkFxUserThread(Toolkit.java:279)
at com.sun.javafx.tk.quantum.QuantumToolkit.checkFxUserThread(QuantumToolkit.java:423)
at javafx.scene.Parent$2.onProposedChange(Parent.java:367)
at com.sun.javafx.collections.VetoableListDecorator.add(VetoableListDecorator.java:206)
at javafx.scene.chart.BarChart.seriesAdded(BarChart.java:293)
at javafx.scene.chart.XYChart.lambda$new$550(XYChart.java:160)
at com.sun.javafx.collections.ListListenerHelper$SingleChange.fireValueChangedEvent(ListListenerHelper.java:164)
at com.sun.javafx.collections.ListListenerHelper.fireValueChangedEvent(ListListenerHelper.java:73)
at javafx.collections.ObservableListBase.fireChange(ObservableListBase.java:233)
at javafx.collections.ListChangeBuilder.commit(ListChangeBuilder.java:482)
at javafx.collections.ListChangeBuilder.endChange(ListChangeBuilder.java:541)
at javafx.collections.ObservableListBase.endChange(ObservableListBase.java:205)
at javafx.collections.ModifiableObservableListBase.add(ModifiableObservableListBase.java:155)
at java.util.AbstractList.add(AbstractList.java:108)
at QuizGUI_classes.StopWatchBar.run(StopWatchBar.java:42)
at java.lang.Thread.run(Thread.java:748)
I have no clue if im on the right path or not, hope someone has some insight.
java multithreading javafx timer
add a comment |
up vote
0
down vote
favorite
Im trying to build a Quizz Application with JavaFX.
The user is supposed to answer as many questions as possible in one minute. I have created a subclass of BarChart that i want to use to visualise the how much time is left. My class implements Runnable because the timer is supposed to run as its own thread (right?).
I want to set the bargraph to 60, and then decrease the bar for each second. I have tried different ways to do this but none of them are succesful.
Heres what the class look like now:
public class StopWatchBar extends BarChart implements Runnable {
public StopWatchBar() {
super(new CategoryAxis(), new NumberAxis(0, 60, 1));
super.setTitle("Time");
this.setMaxWidth(200);
this.setScaleShape(true);
this.setAnimated(false);
this.setCenterShape(true);
}
@Override
public void run() {
XYChart.Series timeDataSeries = new XYChart.Series();
timeDataSeries.getData().add(new XYChart.Data<String, Integer>("", 60));
this.getData().add(timeDataSeries);
int counterSeconds = 60;
long startTime = System.currentTimeMillis();
long endTime = System.currentTimeMillis() + (counterSeconds * 1000);
long startTimePlusOneSecond = startTime + 1000;
while (startTime < endTime) {
if (startTime == startTimePlusOneSecond) {
timeDataSeries.getData().clear();
timeDataSeries.getData().add(new XYChart.Data<String, Number>("", counterSeconds));
counterSeconds--;
startTimePlusOneSecond += 1000;
}
startTime = System.currentTimeMillis();
}
}
}
I have created an object of the class as an instance object in my Scene in PrimaryStage.
In the same scene i also have a button that i want to use to test to execute the counter:
Like this:
timerTestButton.setOnAction(actionEvent -> {
Thread timeBarRunner = new Thread(timeBar);
timeBarRunner.start();
});
When i push the button in the UI i get the Exception:
Exception in thread "Thread-4" java.lang.IllegalStateException: Not on FX application thread; currentThread = Thread-4
at com.sun.javafx.tk.Toolkit.checkFxUserThread(Toolkit.java:279)
at com.sun.javafx.tk.quantum.QuantumToolkit.checkFxUserThread(QuantumToolkit.java:423)
at javafx.scene.Parent$2.onProposedChange(Parent.java:367)
at com.sun.javafx.collections.VetoableListDecorator.add(VetoableListDecorator.java:206)
at javafx.scene.chart.BarChart.seriesAdded(BarChart.java:293)
at javafx.scene.chart.XYChart.lambda$new$550(XYChart.java:160)
at com.sun.javafx.collections.ListListenerHelper$SingleChange.fireValueChangedEvent(ListListenerHelper.java:164)
at com.sun.javafx.collections.ListListenerHelper.fireValueChangedEvent(ListListenerHelper.java:73)
at javafx.collections.ObservableListBase.fireChange(ObservableListBase.java:233)
at javafx.collections.ListChangeBuilder.commit(ListChangeBuilder.java:482)
at javafx.collections.ListChangeBuilder.endChange(ListChangeBuilder.java:541)
at javafx.collections.ObservableListBase.endChange(ObservableListBase.java:205)
at javafx.collections.ModifiableObservableListBase.add(ModifiableObservableListBase.java:155)
at java.util.AbstractList.add(AbstractList.java:108)
at QuizGUI_classes.StopWatchBar.run(StopWatchBar.java:42)
at java.lang.Thread.run(Thread.java:748)
I have no clue if im on the right path or not, hope someone has some insight.
java multithreading javafx timer
There is a dedicated thread you have to use when modifying the state of GUI components. I'm not familiar with JavaFX, but typically there would be some utility method in the API to enqueue a Runnable or a Callable or whatever to be run in the appropriate thread.
– OpenSauce
Nov 10 at 20:34
1
In JavaFX, the utility method that OpenSauce refers to isPlatform.runLater(Runnable)
. Though it'd probably be easier to implement this using the animation API.
– Slaw
Nov 11 at 0:57
add a comment |
up vote
0
down vote
favorite
up vote
0
down vote
favorite
Im trying to build a Quizz Application with JavaFX.
The user is supposed to answer as many questions as possible in one minute. I have created a subclass of BarChart that i want to use to visualise the how much time is left. My class implements Runnable because the timer is supposed to run as its own thread (right?).
I want to set the bargraph to 60, and then decrease the bar for each second. I have tried different ways to do this but none of them are succesful.
Heres what the class look like now:
public class StopWatchBar extends BarChart implements Runnable {
public StopWatchBar() {
super(new CategoryAxis(), new NumberAxis(0, 60, 1));
super.setTitle("Time");
this.setMaxWidth(200);
this.setScaleShape(true);
this.setAnimated(false);
this.setCenterShape(true);
}
@Override
public void run() {
XYChart.Series timeDataSeries = new XYChart.Series();
timeDataSeries.getData().add(new XYChart.Data<String, Integer>("", 60));
this.getData().add(timeDataSeries);
int counterSeconds = 60;
long startTime = System.currentTimeMillis();
long endTime = System.currentTimeMillis() + (counterSeconds * 1000);
long startTimePlusOneSecond = startTime + 1000;
while (startTime < endTime) {
if (startTime == startTimePlusOneSecond) {
timeDataSeries.getData().clear();
timeDataSeries.getData().add(new XYChart.Data<String, Number>("", counterSeconds));
counterSeconds--;
startTimePlusOneSecond += 1000;
}
startTime = System.currentTimeMillis();
}
}
}
I have created an object of the class as an instance object in my Scene in PrimaryStage.
In the same scene i also have a button that i want to use to test to execute the counter:
Like this:
timerTestButton.setOnAction(actionEvent -> {
Thread timeBarRunner = new Thread(timeBar);
timeBarRunner.start();
});
When i push the button in the UI i get the Exception:
Exception in thread "Thread-4" java.lang.IllegalStateException: Not on FX application thread; currentThread = Thread-4
at com.sun.javafx.tk.Toolkit.checkFxUserThread(Toolkit.java:279)
at com.sun.javafx.tk.quantum.QuantumToolkit.checkFxUserThread(QuantumToolkit.java:423)
at javafx.scene.Parent$2.onProposedChange(Parent.java:367)
at com.sun.javafx.collections.VetoableListDecorator.add(VetoableListDecorator.java:206)
at javafx.scene.chart.BarChart.seriesAdded(BarChart.java:293)
at javafx.scene.chart.XYChart.lambda$new$550(XYChart.java:160)
at com.sun.javafx.collections.ListListenerHelper$SingleChange.fireValueChangedEvent(ListListenerHelper.java:164)
at com.sun.javafx.collections.ListListenerHelper.fireValueChangedEvent(ListListenerHelper.java:73)
at javafx.collections.ObservableListBase.fireChange(ObservableListBase.java:233)
at javafx.collections.ListChangeBuilder.commit(ListChangeBuilder.java:482)
at javafx.collections.ListChangeBuilder.endChange(ListChangeBuilder.java:541)
at javafx.collections.ObservableListBase.endChange(ObservableListBase.java:205)
at javafx.collections.ModifiableObservableListBase.add(ModifiableObservableListBase.java:155)
at java.util.AbstractList.add(AbstractList.java:108)
at QuizGUI_classes.StopWatchBar.run(StopWatchBar.java:42)
at java.lang.Thread.run(Thread.java:748)
I have no clue if im on the right path or not, hope someone has some insight.
java multithreading javafx timer
Im trying to build a Quizz Application with JavaFX.
The user is supposed to answer as many questions as possible in one minute. I have created a subclass of BarChart that i want to use to visualise the how much time is left. My class implements Runnable because the timer is supposed to run as its own thread (right?).
I want to set the bargraph to 60, and then decrease the bar for each second. I have tried different ways to do this but none of them are succesful.
Heres what the class look like now:
public class StopWatchBar extends BarChart implements Runnable {
public StopWatchBar() {
super(new CategoryAxis(), new NumberAxis(0, 60, 1));
super.setTitle("Time");
this.setMaxWidth(200);
this.setScaleShape(true);
this.setAnimated(false);
this.setCenterShape(true);
}
@Override
public void run() {
XYChart.Series timeDataSeries = new XYChart.Series();
timeDataSeries.getData().add(new XYChart.Data<String, Integer>("", 60));
this.getData().add(timeDataSeries);
int counterSeconds = 60;
long startTime = System.currentTimeMillis();
long endTime = System.currentTimeMillis() + (counterSeconds * 1000);
long startTimePlusOneSecond = startTime + 1000;
while (startTime < endTime) {
if (startTime == startTimePlusOneSecond) {
timeDataSeries.getData().clear();
timeDataSeries.getData().add(new XYChart.Data<String, Number>("", counterSeconds));
counterSeconds--;
startTimePlusOneSecond += 1000;
}
startTime = System.currentTimeMillis();
}
}
}
I have created an object of the class as an instance object in my Scene in PrimaryStage.
In the same scene i also have a button that i want to use to test to execute the counter:
Like this:
timerTestButton.setOnAction(actionEvent -> {
Thread timeBarRunner = new Thread(timeBar);
timeBarRunner.start();
});
When i push the button in the UI i get the Exception:
Exception in thread "Thread-4" java.lang.IllegalStateException: Not on FX application thread; currentThread = Thread-4
at com.sun.javafx.tk.Toolkit.checkFxUserThread(Toolkit.java:279)
at com.sun.javafx.tk.quantum.QuantumToolkit.checkFxUserThread(QuantumToolkit.java:423)
at javafx.scene.Parent$2.onProposedChange(Parent.java:367)
at com.sun.javafx.collections.VetoableListDecorator.add(VetoableListDecorator.java:206)
at javafx.scene.chart.BarChart.seriesAdded(BarChart.java:293)
at javafx.scene.chart.XYChart.lambda$new$550(XYChart.java:160)
at com.sun.javafx.collections.ListListenerHelper$SingleChange.fireValueChangedEvent(ListListenerHelper.java:164)
at com.sun.javafx.collections.ListListenerHelper.fireValueChangedEvent(ListListenerHelper.java:73)
at javafx.collections.ObservableListBase.fireChange(ObservableListBase.java:233)
at javafx.collections.ListChangeBuilder.commit(ListChangeBuilder.java:482)
at javafx.collections.ListChangeBuilder.endChange(ListChangeBuilder.java:541)
at javafx.collections.ObservableListBase.endChange(ObservableListBase.java:205)
at javafx.collections.ModifiableObservableListBase.add(ModifiableObservableListBase.java:155)
at java.util.AbstractList.add(AbstractList.java:108)
at QuizGUI_classes.StopWatchBar.run(StopWatchBar.java:42)
at java.lang.Thread.run(Thread.java:748)
I have no clue if im on the right path or not, hope someone has some insight.
java multithreading javafx timer
java multithreading javafx timer
edited Nov 10 at 20:26
asked Nov 10 at 20:10
Alfonso
12
12
There is a dedicated thread you have to use when modifying the state of GUI components. I'm not familiar with JavaFX, but typically there would be some utility method in the API to enqueue a Runnable or a Callable or whatever to be run in the appropriate thread.
– OpenSauce
Nov 10 at 20:34
1
In JavaFX, the utility method that OpenSauce refers to isPlatform.runLater(Runnable)
. Though it'd probably be easier to implement this using the animation API.
– Slaw
Nov 11 at 0:57
add a comment |
There is a dedicated thread you have to use when modifying the state of GUI components. I'm not familiar with JavaFX, but typically there would be some utility method in the API to enqueue a Runnable or a Callable or whatever to be run in the appropriate thread.
– OpenSauce
Nov 10 at 20:34
1
In JavaFX, the utility method that OpenSauce refers to isPlatform.runLater(Runnable)
. Though it'd probably be easier to implement this using the animation API.
– Slaw
Nov 11 at 0:57
There is a dedicated thread you have to use when modifying the state of GUI components. I'm not familiar with JavaFX, but typically there would be some utility method in the API to enqueue a Runnable or a Callable or whatever to be run in the appropriate thread.
– OpenSauce
Nov 10 at 20:34
There is a dedicated thread you have to use when modifying the state of GUI components. I'm not familiar with JavaFX, but typically there would be some utility method in the API to enqueue a Runnable or a Callable or whatever to be run in the appropriate thread.
– OpenSauce
Nov 10 at 20:34
1
1
In JavaFX, the utility method that OpenSauce refers to is
Platform.runLater(Runnable)
. Though it'd probably be easier to implement this using the animation API.– Slaw
Nov 11 at 0:57
In JavaFX, the utility method that OpenSauce refers to is
Platform.runLater(Runnable)
. Though it'd probably be easier to implement this using the animation API.– Slaw
Nov 11 at 0:57
add a comment |
1 Answer
1
active
oldest
votes
up vote
0
down vote
Here is an example using Timeline
. The Timeline
is set to run every second. Once the counter reaches zero, the Timeline
stops.
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.chart.BarChart;
import javafx.scene.chart.CategoryAxis;
import javafx.scene.chart.NumberAxis;
import javafx.scene.chart.XYChart;
import javafx.scene.control.Button;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import javafx.util.Duration;
public class BarChartExperiments extends Application {
Timeline timeline;
int counter = 60;
@Override
public void start(Stage primaryStage) throws Exception {
primaryStage.setTitle("BarChart Experiments");
CategoryAxis xAxis = new CategoryAxis();
xAxis.setLabel("Devices");
NumberAxis yAxis = new NumberAxis();
yAxis.setLabel("Visits");
BarChart barChart = new BarChart(xAxis, yAxis);
XYChart.Series dataSeries1 = new XYChart.Series();
dataSeries1.setName("Time");
barChart.getData().add(dataSeries1);
barChart.setAnimated(false);
dataSeries1.getData().add(new XYChart.Data("Time", counter));
timeline = new Timeline(new KeyFrame(Duration.seconds(1), event ->{
dataSeries1.getData().add(new XYChart.Data("Time", --counter));
System.out.println(counter);
if(counter == 0)
{
timeline.stop();
}
}));
timeline.setCycleCount(Timeline.INDEFINITE);
Button button = new Button("Start");
button.setOnAction(event ->{
switch(button.getText())
{
case "Start":
timeline.play();
button.setText("Reset");
break;
case "Reset":
timeline.stop();
button.setText("Start");
counter = 60;
dataSeries1.getData().add(new XYChart.Data("Time", counter));
break;
}
});
VBox vbox = new VBox(barChart, button);
Scene scene = new Scene(vbox, 400, 200);
primaryStage.setScene(scene);
primaryStage.setHeight(600);
primaryStage.setWidth(500);
primaryStage.show();
}
public static void main(String args) {
Application.launch(args);
}
}
Altered code from here
Well @Sedrick, that really helped. The answer was indeed to use the TimeLine to make this happen. You made my day!
– Alfonso
Nov 11 at 11:31
If the answer helped you, either post your solution or accept this as the correct answer.
– Sedrick
Nov 11 at 16:24
add a comment |
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
0
down vote
Here is an example using Timeline
. The Timeline
is set to run every second. Once the counter reaches zero, the Timeline
stops.
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.chart.BarChart;
import javafx.scene.chart.CategoryAxis;
import javafx.scene.chart.NumberAxis;
import javafx.scene.chart.XYChart;
import javafx.scene.control.Button;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import javafx.util.Duration;
public class BarChartExperiments extends Application {
Timeline timeline;
int counter = 60;
@Override
public void start(Stage primaryStage) throws Exception {
primaryStage.setTitle("BarChart Experiments");
CategoryAxis xAxis = new CategoryAxis();
xAxis.setLabel("Devices");
NumberAxis yAxis = new NumberAxis();
yAxis.setLabel("Visits");
BarChart barChart = new BarChart(xAxis, yAxis);
XYChart.Series dataSeries1 = new XYChart.Series();
dataSeries1.setName("Time");
barChart.getData().add(dataSeries1);
barChart.setAnimated(false);
dataSeries1.getData().add(new XYChart.Data("Time", counter));
timeline = new Timeline(new KeyFrame(Duration.seconds(1), event ->{
dataSeries1.getData().add(new XYChart.Data("Time", --counter));
System.out.println(counter);
if(counter == 0)
{
timeline.stop();
}
}));
timeline.setCycleCount(Timeline.INDEFINITE);
Button button = new Button("Start");
button.setOnAction(event ->{
switch(button.getText())
{
case "Start":
timeline.play();
button.setText("Reset");
break;
case "Reset":
timeline.stop();
button.setText("Start");
counter = 60;
dataSeries1.getData().add(new XYChart.Data("Time", counter));
break;
}
});
VBox vbox = new VBox(barChart, button);
Scene scene = new Scene(vbox, 400, 200);
primaryStage.setScene(scene);
primaryStage.setHeight(600);
primaryStage.setWidth(500);
primaryStage.show();
}
public static void main(String args) {
Application.launch(args);
}
}
Altered code from here
Well @Sedrick, that really helped. The answer was indeed to use the TimeLine to make this happen. You made my day!
– Alfonso
Nov 11 at 11:31
If the answer helped you, either post your solution or accept this as the correct answer.
– Sedrick
Nov 11 at 16:24
add a comment |
up vote
0
down vote
Here is an example using Timeline
. The Timeline
is set to run every second. Once the counter reaches zero, the Timeline
stops.
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.chart.BarChart;
import javafx.scene.chart.CategoryAxis;
import javafx.scene.chart.NumberAxis;
import javafx.scene.chart.XYChart;
import javafx.scene.control.Button;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import javafx.util.Duration;
public class BarChartExperiments extends Application {
Timeline timeline;
int counter = 60;
@Override
public void start(Stage primaryStage) throws Exception {
primaryStage.setTitle("BarChart Experiments");
CategoryAxis xAxis = new CategoryAxis();
xAxis.setLabel("Devices");
NumberAxis yAxis = new NumberAxis();
yAxis.setLabel("Visits");
BarChart barChart = new BarChart(xAxis, yAxis);
XYChart.Series dataSeries1 = new XYChart.Series();
dataSeries1.setName("Time");
barChart.getData().add(dataSeries1);
barChart.setAnimated(false);
dataSeries1.getData().add(new XYChart.Data("Time", counter));
timeline = new Timeline(new KeyFrame(Duration.seconds(1), event ->{
dataSeries1.getData().add(new XYChart.Data("Time", --counter));
System.out.println(counter);
if(counter == 0)
{
timeline.stop();
}
}));
timeline.setCycleCount(Timeline.INDEFINITE);
Button button = new Button("Start");
button.setOnAction(event ->{
switch(button.getText())
{
case "Start":
timeline.play();
button.setText("Reset");
break;
case "Reset":
timeline.stop();
button.setText("Start");
counter = 60;
dataSeries1.getData().add(new XYChart.Data("Time", counter));
break;
}
});
VBox vbox = new VBox(barChart, button);
Scene scene = new Scene(vbox, 400, 200);
primaryStage.setScene(scene);
primaryStage.setHeight(600);
primaryStage.setWidth(500);
primaryStage.show();
}
public static void main(String args) {
Application.launch(args);
}
}
Altered code from here
Well @Sedrick, that really helped. The answer was indeed to use the TimeLine to make this happen. You made my day!
– Alfonso
Nov 11 at 11:31
If the answer helped you, either post your solution or accept this as the correct answer.
– Sedrick
Nov 11 at 16:24
add a comment |
up vote
0
down vote
up vote
0
down vote
Here is an example using Timeline
. The Timeline
is set to run every second. Once the counter reaches zero, the Timeline
stops.
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.chart.BarChart;
import javafx.scene.chart.CategoryAxis;
import javafx.scene.chart.NumberAxis;
import javafx.scene.chart.XYChart;
import javafx.scene.control.Button;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import javafx.util.Duration;
public class BarChartExperiments extends Application {
Timeline timeline;
int counter = 60;
@Override
public void start(Stage primaryStage) throws Exception {
primaryStage.setTitle("BarChart Experiments");
CategoryAxis xAxis = new CategoryAxis();
xAxis.setLabel("Devices");
NumberAxis yAxis = new NumberAxis();
yAxis.setLabel("Visits");
BarChart barChart = new BarChart(xAxis, yAxis);
XYChart.Series dataSeries1 = new XYChart.Series();
dataSeries1.setName("Time");
barChart.getData().add(dataSeries1);
barChart.setAnimated(false);
dataSeries1.getData().add(new XYChart.Data("Time", counter));
timeline = new Timeline(new KeyFrame(Duration.seconds(1), event ->{
dataSeries1.getData().add(new XYChart.Data("Time", --counter));
System.out.println(counter);
if(counter == 0)
{
timeline.stop();
}
}));
timeline.setCycleCount(Timeline.INDEFINITE);
Button button = new Button("Start");
button.setOnAction(event ->{
switch(button.getText())
{
case "Start":
timeline.play();
button.setText("Reset");
break;
case "Reset":
timeline.stop();
button.setText("Start");
counter = 60;
dataSeries1.getData().add(new XYChart.Data("Time", counter));
break;
}
});
VBox vbox = new VBox(barChart, button);
Scene scene = new Scene(vbox, 400, 200);
primaryStage.setScene(scene);
primaryStage.setHeight(600);
primaryStage.setWidth(500);
primaryStage.show();
}
public static void main(String args) {
Application.launch(args);
}
}
Altered code from here
Here is an example using Timeline
. The Timeline
is set to run every second. Once the counter reaches zero, the Timeline
stops.
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.chart.BarChart;
import javafx.scene.chart.CategoryAxis;
import javafx.scene.chart.NumberAxis;
import javafx.scene.chart.XYChart;
import javafx.scene.control.Button;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import javafx.util.Duration;
public class BarChartExperiments extends Application {
Timeline timeline;
int counter = 60;
@Override
public void start(Stage primaryStage) throws Exception {
primaryStage.setTitle("BarChart Experiments");
CategoryAxis xAxis = new CategoryAxis();
xAxis.setLabel("Devices");
NumberAxis yAxis = new NumberAxis();
yAxis.setLabel("Visits");
BarChart barChart = new BarChart(xAxis, yAxis);
XYChart.Series dataSeries1 = new XYChart.Series();
dataSeries1.setName("Time");
barChart.getData().add(dataSeries1);
barChart.setAnimated(false);
dataSeries1.getData().add(new XYChart.Data("Time", counter));
timeline = new Timeline(new KeyFrame(Duration.seconds(1), event ->{
dataSeries1.getData().add(new XYChart.Data("Time", --counter));
System.out.println(counter);
if(counter == 0)
{
timeline.stop();
}
}));
timeline.setCycleCount(Timeline.INDEFINITE);
Button button = new Button("Start");
button.setOnAction(event ->{
switch(button.getText())
{
case "Start":
timeline.play();
button.setText("Reset");
break;
case "Reset":
timeline.stop();
button.setText("Start");
counter = 60;
dataSeries1.getData().add(new XYChart.Data("Time", counter));
break;
}
});
VBox vbox = new VBox(barChart, button);
Scene scene = new Scene(vbox, 400, 200);
primaryStage.setScene(scene);
primaryStage.setHeight(600);
primaryStage.setWidth(500);
primaryStage.show();
}
public static void main(String args) {
Application.launch(args);
}
}
Altered code from here
answered Nov 11 at 9:58
Sedrick
5,79531838
5,79531838
Well @Sedrick, that really helped. The answer was indeed to use the TimeLine to make this happen. You made my day!
– Alfonso
Nov 11 at 11:31
If the answer helped you, either post your solution or accept this as the correct answer.
– Sedrick
Nov 11 at 16:24
add a comment |
Well @Sedrick, that really helped. The answer was indeed to use the TimeLine to make this happen. You made my day!
– Alfonso
Nov 11 at 11:31
If the answer helped you, either post your solution or accept this as the correct answer.
– Sedrick
Nov 11 at 16:24
Well @Sedrick, that really helped. The answer was indeed to use the TimeLine to make this happen. You made my day!
– Alfonso
Nov 11 at 11:31
Well @Sedrick, that really helped. The answer was indeed to use the TimeLine to make this happen. You made my day!
– Alfonso
Nov 11 at 11:31
If the answer helped you, either post your solution or accept this as the correct answer.
– Sedrick
Nov 11 at 16:24
If the answer helped you, either post your solution or accept this as the correct answer.
– Sedrick
Nov 11 at 16:24
add a comment |
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53242990%2fhow-to-make-a-barchart-behave-like-a-timer%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
There is a dedicated thread you have to use when modifying the state of GUI components. I'm not familiar with JavaFX, but typically there would be some utility method in the API to enqueue a Runnable or a Callable or whatever to be run in the appropriate thread.
– OpenSauce
Nov 10 at 20:34
1
In JavaFX, the utility method that OpenSauce refers to is
Platform.runLater(Runnable)
. Though it'd probably be easier to implement this using the animation API.– Slaw
Nov 11 at 0:57