我正在尝试使用JavaFX构建Quizz应用程序。 用户应该在一分钟内回答尽可能多的问题。我创建了BarChart的子类,我想用它来可视化剩余的时间。我的类实现了Runnable,因为计时器应该作为自己的线程运行(对吗?)。
我想将条形图设置为60,然后每秒减小一次条形。我尝试了不同的方法来执行此操作,但没有一个成功。
这是该类现在的样子:
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();
}
}
}
我已经在PrimaryStage中的Scene中创建了该类的对象作为实例对象。 在同一场景中,我还有一个按钮,我想使用它来测试执行计数器: 像这样:
timerTestButton.setOnAction(actionEvent -> {
Thread timeBarRunner = new Thread(timeBar);
timeBarRunner.start();
});
当我按下UI中的按钮时,出现异常:
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)
我不知道我是否在正确的道路上,希望有人对此有所了解。
答案 0 :(得分:0)
以下是使用Timeline
的示例。 Timeline
设置为每秒运行一次。一旦计数器达到零,Timeline
就会停止。
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);
}
}
来自here
的更改代码