Как заставить BarChart вести себя как таймер? - PullRequest
0 голосов
/ 10 ноября 2018

Я пытаюсь создать приложение Quizz с JavaFX. Пользователь должен ответить на как можно больше вопросов за одну минуту. Я создал подкласс 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. В той же сцене у меня также есть кнопка, которую я хочу использовать для проверки выполнения счетчика: Как это:

timerTestButton.setOnAction(actionEvent -> {
        Thread timeBarRunner = new Thread(timeBar);
        timeBarRunner.start();
        });

Когда я нажимаю кнопку в пользовательском интерфейсе, я получаю исключение:

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)

Я понятия не имею, нахожусь ли я на правильном пути или нет, надеюсь, у кого-то есть понимание.

1 Ответ

0 голосов
/ 11 ноября 2018

Вот пример использования 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);
    }
}

Измененный код с здесь

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...