1
0
Fork 0
mirror of https://gitlab.com/kauron/jstudy synced 2024-12-22 16:33:33 +01:00

Test: added Pause checkbox

This commit is contained in:
Carlos Galindo 2019-09-13 00:55:07 +02:00
parent 7fe80b07ec
commit e9e2c0704d
Signed by: kauron
GPG key ID: 83E68706DEE119A3
3 changed files with 93 additions and 61 deletions

View file

@ -2,25 +2,22 @@ package es.kauron.jstudy.controller;
import es.kauron.jstudy.model.AppPrefs; import es.kauron.jstudy.model.AppPrefs;
import es.kauron.jstudy.model.TestItem; import es.kauron.jstudy.model.TestItem;
import javafx.application.Platform; import es.kauron.jstudy.util.Clock;
import javafx.beans.binding.Bindings; import javafx.beans.binding.Bindings;
import javafx.beans.property.*; import javafx.beans.property.*;
import javafx.event.ActionEvent; import javafx.event.ActionEvent;
import javafx.fxml.FXML; import javafx.fxml.FXML;
import javafx.fxml.Initializable; import javafx.fxml.Initializable;
import javafx.scene.control.Button; import javafx.scene.control.*;
import javafx.scene.control.Label; import javafx.scene.layout.Pane;
import javafx.scene.control.ProgressBar;
import javafx.scene.control.TextField;
import javafx.scene.layout.HBox;
import java.net.URL; import java.net.URL;
import java.util.List; import java.util.List;
import java.util.ResourceBundle; import java.util.ResourceBundle;
import java.util.Timer;
import java.util.TimerTask;
public class TestController implements Initializable { public class TestController implements Initializable {
private static final TestItem ending = new TestItem("That's it!", "");
@FXML @FXML
private Label question, prevQuestion, prevAnswer, correctAnswer, progressLabel, correctLabel; private Label question, prevQuestion, prevAnswer, correctAnswer, progressLabel, correctLabel;
@FXML @FXML
@ -28,9 +25,11 @@ public class TestController implements Initializable {
@FXML @FXML
private ProgressBar progress; private ProgressBar progress;
@FXML @FXML
private HBox feedback; private Pane feedback, buttonBox;
@FXML @FXML
private Button skipButton; private Button skipButton;
@FXML
private CheckBox pauseCheckBox;
private final SimpleBooleanProperty correctingError = new SimpleBooleanProperty(false); private final SimpleBooleanProperty correctingError = new SimpleBooleanProperty(false);
private List<TestItem> list; private List<TestItem> list;
@ -38,19 +37,17 @@ public class TestController implements Initializable {
private final ObjectProperty<TestItem> item = new SimpleObjectProperty<>(); private final ObjectProperty<TestItem> item = new SimpleObjectProperty<>();
private final IntegerProperty done = new SimpleIntegerProperty(0); private final IntegerProperty done = new SimpleIntegerProperty(0);
// Time accounting // Time accounting
private final IntegerProperty seconds = new SimpleIntegerProperty(0); private final Clock clock = new Clock();
private final IntegerProperty minutes = new SimpleIntegerProperty(0);
private final Timer timer = new Timer();
@Override @Override
public void initialize(URL url, ResourceBundle resourceBundle) { public void initialize(URL url, ResourceBundle resourceBundle) {
skipButton.disableProperty().bind(correctingError); skipButton.disableProperty().bind(correctingError);
feedback.visibleProperty().bind(AppPrefs.showFeedback); feedback.visibleProperty().bind(AppPrefs.showFeedback);
seconds.addListener((obj, o, n) -> { answer.disableProperty().bind(pauseCheckBox.selectedProperty());
if (n.intValue() == 60) { buttonBox.disableProperty().bind(pauseCheckBox.selectedProperty());
minutes.set(minutes.get() + 1); pauseCheckBox.selectedProperty().addListener((obj, o, n) -> {
seconds.set(0); if (n) clock.pause();
} else clock.play();
}); });
} }
@ -58,9 +55,9 @@ public class TestController implements Initializable {
this.list = list; this.list = list;
int total = list.size(); int total = list.size();
progressLabel.textProperty().bind(Bindings.format( progressLabel.textProperty().bind(Bindings.format(
String.format("%%.2f%%%% %%d / %d %%d mistakes %%02d:%%02d", total), String.format("%%.2f%%%% %%d / %d %%d mistakes %%s", total),
done.multiply(100.0).divide(total), done, done.multiply(100.0).divide(total), done,
errors, minutes, seconds)); errors, clock.timeProperty()));
progress.progressProperty().bind(done.divide((double) total)); progress.progressProperty().bind(done.divide((double) total));
item.addListener((obj, o, n) -> { item.addListener((obj, o, n) -> {
if (o != null) { if (o != null) {
@ -69,12 +66,7 @@ public class TestController implements Initializable {
} }
question.setText(n.getQuestion()); question.setText(n.getQuestion());
}); });
timer.schedule(new TimerTask() { clock.play();
@Override
public void run() {
Platform.runLater(() -> seconds.set(seconds.get() + 1));
}
}, 0, 1000);
onSkipAction(null); onSkipAction(null);
} }
@ -134,8 +126,8 @@ public class TestController implements Initializable {
@FXML @FXML
private void onEndAction(ActionEvent event) { private void onEndAction(ActionEvent event) {
answer.setText(""); answer.setText("");
answer.setDisable(true); item.set(ending);
question.setText("That's it!"); pauseCheckBox.setSelected(true);
timer.cancel(); pauseCheckBox.setDisable(true);
} }
} }

View file

@ -0,0 +1,46 @@
package es.kauron.jstudy.util;
import javafx.application.Platform;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import java.util.Timer;
import java.util.TimerTask;
public class Clock {
private static final short SEC_TO_MIN = 60;
private short seconds = 0;
private Timer timer = new Timer();
private TimerTask task;
private final StringProperty time = new SimpleStringProperty();
public Clock() {
setObservable();
}
public StringProperty timeProperty() {
return time;
}
public void play() {
if (task != null) task.cancel();
task = new TimerTask() {
@Override
public void run() {
seconds++;
Platform.runLater(() -> setObservable());
}
};
timer.schedule(task, 0, 1000);
}
public void pause() {
if (task != null)
task.cancel();
task = null;
}
private void setObservable() {
time.set(String.format("%02d:%02d", seconds / SEC_TO_MIN, seconds % SEC_TO_MIN));
}
}

View file

@ -4,78 +4,72 @@
<?import javafx.scene.control.*?> <?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?> <?import javafx.scene.layout.*?>
<?import javafx.scene.text.Font?> <?import javafx.scene.text.Font?>
<BorderPane xmlns="http://javafx.com/javafx/8.0.202-ea" xmlns:fx="http://javafx.com/fxml/1" <BorderPane stylesheets="@../css/test.css" xmlns="http://javafx.com/javafx/8.0.202-ea" xmlns:fx="http://javafx.com/fxml/1" fx:controller="es.kauron.jstudy.controller.TestController">
fx:controller="es.kauron.jstudy.controller.TestController" stylesheets="@../css/test.css">
<center> <center>
<VBox minHeight="280.0" minWidth="360.0" spacing="10.0"> <VBox minHeight="280.0" minWidth="360.0" spacing="10.0">
<children> <children>
<Label fx:id="question" text="Question" textOverrun="CLIP" wrapText="true" VBox.vgrow="ALWAYS"> <Label fx:id="question" text="Question" textOverrun="CLIP" wrapText="true" VBox.vgrow="ALWAYS">
<font> <font>
<Font size="30.0"/> <Font size="30.0" />
</font> </font>
</Label> </Label>
<TextField fx:id="answer"> <TextField fx:id="answer">
<VBox.margin> <VBox.margin>
<Insets top="5.0"/> <Insets top="5.0" />
</VBox.margin> </VBox.margin>
</TextField> </TextField>
<Separator/> <Separator />
<HBox fx:id="feedback" alignment="BOTTOM_CENTER" VBox.vgrow="ALWAYS"> <HBox fx:id="feedback" alignment="BOTTOM_CENTER" VBox.vgrow="ALWAYS">
<children> <children>
<GridPane hgap="10.0" maxWidth="1.7976931348623157E308" HBox.hgrow="ALWAYS"> <GridPane hgap="10.0" maxWidth="1.7976931348623157E308" HBox.hgrow="ALWAYS">
<columnConstraints> <columnConstraints>
<ColumnConstraints fillWidth="false" halignment="RIGHT" hgrow="NEVER"/> <ColumnConstraints fillWidth="false" halignment="RIGHT" hgrow="NEVER" />
<ColumnConstraints fillWidth="false" hgrow="ALWAYS" maxWidth="1.7976931348623157E308"/> <ColumnConstraints fillWidth="false" hgrow="ALWAYS" maxWidth="1.7976931348623157E308" />
</columnConstraints> </columnConstraints>
<rowConstraints> <rowConstraints>
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES"/> <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES"/> <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES"/> <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
</rowConstraints> </rowConstraints>
<children> <children>
<Label text="Previous question" wrapText="true"/> <Label text="Previous question" wrapText="true" />
<Label fx:id="prevQuestion" maxWidth="1.7976931348623157E308" styleClass="feedbackText" wrapText="true" <Label fx:id="prevQuestion" maxWidth="1.7976931348623157E308" styleClass="feedbackText" wrapText="true" GridPane.columnIndex="1" />
GridPane.columnIndex="1"/> <Label text="Previous answer" wrapText="true" GridPane.rowIndex="1" />
<Label text="Previous answer" wrapText="true" GridPane.rowIndex="1"/> <Label fx:id="prevAnswer" maxWidth="1.7976931348623157E308" styleClass="answer, feedbackText" wrapText="true" GridPane.columnIndex="1" GridPane.rowIndex="1" />
<Label fx:id="prevAnswer" maxWidth="1.7976931348623157E308" styleClass="answer, feedbackText" <Label fx:id="correctLabel" text="Correct answer" wrapText="true" GridPane.rowIndex="2" />
wrapText="true" GridPane.columnIndex="1" GridPane.rowIndex="1"/> <Label fx:id="correctAnswer" maxWidth="1.7976931348623157E308" styleClass="feedbackText" wrapText="true" GridPane.columnIndex="1" GridPane.rowIndex="2" />
<Label fx:id="correctLabel" text="Correct answer" wrapText="true" GridPane.rowIndex="2"/>
<Label fx:id="correctAnswer" maxWidth="1.7976931348623157E308" styleClass="feedbackText" wrapText="true"
GridPane.columnIndex="1" GridPane.rowIndex="2"/>
</children> </children>
</GridPane> </GridPane>
</children> </children>
</HBox> </HBox>
</children> </children>
<BorderPane.margin> <BorderPane.margin>
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0"/> <Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
</BorderPane.margin> </BorderPane.margin>
</VBox> </VBox>
</center> </center>
<bottom> <bottom>
<VBox alignment="CENTER" BorderPane.alignment="CENTER"> <VBox alignment="CENTER" BorderPane.alignment="CENTER">
<children> <children>
<Separator prefWidth="200.0"/> <Separator prefWidth="200.0" />
<Label fx:id="progressLabel" alignment="CENTER" contentDisplay="TOP" maxWidth="1.7976931348623157E308" <Label fx:id="progressLabel" alignment="CENTER" contentDisplay="TOP" maxWidth="1.7976931348623157E308" text="1/40" />
text="1/40"/> <ProgressBar fx:id="progress" maxWidth="1.7976931348623157E308" progress="0.0" />
<ProgressBar fx:id="progress" maxWidth="1.7976931348623157E308" progress="0.0"/>
</children> </children>
<BorderPane.margin> <BorderPane.margin>
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0"/> <Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
</BorderPane.margin> </BorderPane.margin>
</VBox> </VBox>
</bottom> </bottom>
<right> <right>
<VBox alignment="TOP_RIGHT" spacing="10.0" BorderPane.alignment="CENTER"> <VBox alignment="TOP_RIGHT" spacing="10.0" BorderPane.alignment="CENTER">
<children> <VBox fx:id="buttonBox" alignment="TOP_RIGHT" spacing="10.0" BorderPane.alignment="CENTER">
<Button defaultButton="true" focusTraversable="false" onAction="#onNextAction" prefWidth="110.0" text="_Next"/> <Button defaultButton="true" focusTraversable="false" onAction="#onNextAction" prefWidth="110.0" text="_Next" />
<Button fx:id="skipButton" cancelButton="true" focusTraversable="false" onAction="#onSkipAction" <Button fx:id="skipButton" cancelButton="true" focusTraversable="false" onAction="#onSkipAction" prefWidth="110.0" text="_Skip question" />
prefWidth="110.0" text="_Skip question"/> <Button cancelButton="true" focusTraversable="false" layoutX="10.0" layoutY="48.0" onAction="#onEndAction" prefWidth="110.0" text="_End test" />
<Button cancelButton="true" focusTraversable="false" layoutX="10.0" layoutY="48.0" onAction="#onEndAction" </VBox>
prefWidth="110.0" text="_End test"/> <CheckBox fx:id="pauseCheckBox" focusTraversable="false" maxWidth="1.7976931348623157E308" text="_Pause" />
</children>
<BorderPane.margin> <BorderPane.margin>
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0"/> <Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
</BorderPane.margin> </BorderPane.margin>
</VBox> </VBox>
</right> </right>