mirror of
https://gitlab.com/kauron/jstudy
synced 2024-12-22 08:23:33 +01:00
Test: added Pause checkbox
This commit is contained in:
parent
7fe80b07ec
commit
e9e2c0704d
3 changed files with 93 additions and 61 deletions
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
46
src/main/java/es/kauron/jstudy/util/Clock.java
Normal file
46
src/main/java/es/kauron/jstudy/util/Clock.java
Normal 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));
|
||||||
|
}
|
||||||
|
}
|
|
@ -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>
|
||||||
|
|
Loading…
Reference in a new issue