Instructions
Requirements and Specifications
- System displays the following objects on the GUI.
- Welcome. Includes a welcome message to the game.
- Player name label and text entry box.
- Radio buttons to select the problem type (Operation).
- Label and text box to enter the low value for the range of factors.
- Label and text box to enter the high value for the range of factors.
- Label and text box to enter the number of problems to work.
- Button to start the FlashCards.
- Label to display the problem.
- Text box to enter the response to the displayed problem.
- Label to display info about the response – Correct, Incorrect, correct answer.
- Label to display the score, the number of problems answered correctly.
- Label to display the score as a percentage of the total problems, e.g., 67.7.
- Play Again button. Button reads “Play Again”.
- Classes: There is only 1 class for Project 4a. At this time, the class will not instantiate objects from the other classes developed in the project series.
- Objects. Objects from the following classes are required.
- Label
- TextField
- Button
- VBox or HBox
- Pane
- RadioButton
- ToggleGroup
- The JavaFX class consists of 3 phases. Use this in your Design discussion.
- Instantiate JavaFX objects (nodes) for the GUI.
- Set properties for the objects to have them appear as you intend.
- Use subsection comments to identify the different GUI object-related code.
- Add objects to the Pane object and position them appropriately.
- Use methods getChildren().addAll and setLayoutX / setLayoutY methods.
- Declare the Scene object, invoke Stage methods setScene and show.
- Name your source code class as follows: YourName_Project4.java. You should put all classes in a single .java file, so you submit only one java file.
- Name your Word document as follows: YourName_Project4.doc
Source Code
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.Pane;
import javafx.scene.text.Font;
import javafx.stage.Stage;
import java.util.Random;
/**
* Main driver class of the application
*/
public class YourName_Project4 extends Application {
private enum Operation {
Addition, Subtraction, Multiplication, Division;
public int make(int a, int b) {
switch (this) {
case Addition:
return a+b;
case Subtraction:
return a-b;
case Multiplication:
return a*b;
case Division:
return a/b;
default:
throw new IllegalStateException();
}
}
@Override
public String toString() {
switch (this) {
case Addition:
return "+";
case Subtraction:
return "-";
case Multiplication:
return "*";
case Division:
return "/";
default:
throw new IllegalStateException();
}
}
}
private Operation operation = Operation.Addition;
private String name;
private Integer lowest;
private Integer highest;
private Integer number;
private int op1;
private int op2;
private int taskScore;
private int taskCounter;
/**
* Overridden start method of Application
*
* @param stage to start
* @throws Exception on any error
*/
@Override
public void start(Stage stage) throws Exception {
// Instantiate node objects and set properties
// Top Section
Label lWelcome = new Label("Welcome to 3312 FlashCards!");
Label lName = new Label("Name");
TextField tfName = new TextField();
// Left Middle Section
Label lOperation = new Label("Operation");
ToggleGroup tgOperation = new ToggleGroup();
RadioButton rbAddition = new RadioButton("Addition");
RadioButton rbSubtraction = new RadioButton("Subtraction");
RadioButton rbMultiplication = new RadioButton("Multiplication");
RadioButton rbDivision = new RadioButton("Division");
Label lRangeOfFactorValues = new Label("Range of Factor Values");
Label lLowest = new Label("Lowest");
Label lHighest = new Label("Highest");
TextField tfLowest = new TextField();
TextField tfHighest = new TextField();
Label lNumberOfProblems = new Label("Number of Problems");
TextField tfNumberOfProblems = new TextField();
Button bBegin = new Button("Begin");
// Right Middle Section
Label lCardTask = new Label();
TextField tfAnswer = new TextField();
Label lCheck = new Label();
Label lScore = new Label("Score");
Label lScorePct = new Label("ScorePct");
Label lScoreValue = new Label("0.0");
Label lScorePctValue = new Label("0.0");
// Bottom Section
Button bPlayAgain = new Button("PlayAgain");
// Instantiate root
Pane pane = new AnchorPane();
pane.getChildren().addAll(lWelcome, lName, tfName);
pane.getChildren().addAll(lOperation, rbAddition, rbSubtraction, rbMultiplication, rbDivision);
pane.getChildren().addAll(lRangeOfFactorValues, lLowest, lHighest, tfLowest, tfHighest, lNumberOfProblems, tfNumberOfProblems, bBegin);
pane.getChildren().addAll(lCardTask, tfAnswer, lCheck, lScore, lScorePct, lScoreValue, lScorePctValue, bPlayAgain);
// Position nodes and size nodes
// Top Section
lWelcome.setLayoutX(133);
lWelcome.setLayoutY(34);
tfName.setLayoutX(236);
tfName.setLayoutY(74);
lName.setLayoutX(195);
lName.setLayoutY(78);
// Left Section
lOperation.setLayoutX(56);
lOperation.setLayoutY(108);
rbAddition.setLayoutX(56);
rbAddition.setLayoutY(132);
rbSubtraction.setLayoutX(56);
rbSubtraction.setLayoutY(156);
rbMultiplication.setLayoutX(56);
rbMultiplication.setLayoutY(180);
rbDivision.setLayoutX(56);
rbDivision.setLayoutY(204);
lRangeOfFactorValues.setLayoutX(60);
lRangeOfFactorValues.setLayoutY(251);
lLowest.setLayoutX(60);
lLowest.setLayoutY(275);
lHighest.setLayoutX(135);
lHighest.setLayoutY(275);
tfLowest.setLayoutX(58);
tfLowest.setLayoutY(292);
tfHighest.setLayoutX(134);
tfHighest.setLayoutY(292);
lNumberOfProblems.setLayoutX(68);
lNumberOfProblems.setLayoutY(322);
tfNumberOfProblems.setLayoutX(100);
tfNumberOfProblems.setLayoutY(346);
bBegin.setLayoutX(101);
bBegin.setLayoutY(385);
// Right Section
lCardTask.setLayoutX(246);
lCardTask.setLayoutY(180);
tfAnswer.setLayoutX(419);
tfAnswer.setLayoutY(188);
lCheck.setLayoutX(310);
lCheck.setLayoutY(222);
lScore.setLayoutX(342);
lScore.setLayoutY(275);
lScorePct.setLayoutX(342);
lScorePct.setLayoutY(309);
lScoreValue.setLayoutX(416);
lScoreValue.setLayoutY(276);
lScorePctValue.setLayoutX(416);
lScorePctValue.setLayoutY(309);
// Bottom Section
bPlayAgain.setLayoutX(369);
bPlayAgain.setLayoutY(385);
// Options
// Top Section
lWelcome.setFont(new Font("System Bold", 20));
tfName.setOnAction(e -> {
getName(tfName);
if (name != null) {
rbAddition.requestFocus();
}
});
// Left Section
rbAddition.setSelected(true);
rbAddition.setToggleGroup(tgOperation);
rbAddition.setOnAction(e -> {
operation = Operation.Addition;
rbSubtraction.requestFocus();
});
rbAddition.getToggleGroup().selectedToggleProperty().addListener((observable, oldValue, newValue) -> {
if (newValue.isSelected()) {
operation = Operation.Addition;
}
});
rbSubtraction.setToggleGroup(tgOperation);
rbSubtraction.setOnAction(e -> {
operation = Operation.Subtraction;
rbMultiplication.requestFocus();
});
rbSubtraction.getToggleGroup().selectedToggleProperty().addListener((observable, oldValue, newValue) -> {
if (newValue.isSelected()) {
operation = Operation.Subtraction;
}
});
rbMultiplication.setToggleGroup(tgOperation);
rbMultiplication.setOnAction(e -> {
operation = Operation.Multiplication;
rbDivision.requestFocus();
});
rbMultiplication.getToggleGroup().selectedToggleProperty().addListener((observable, oldValue, newValue) -> {
if (newValue.isSelected()) {
operation = Operation.Multiplication;
}
});
rbDivision.setToggleGroup(tgOperation);
rbDivision.setOnAction(e -> {
operation = Operation.Division;
tfLowest.requestFocus();
});
rbDivision.getToggleGroup().selectedToggleProperty().addListener((observable, oldValue, newValue) -> {
if (newValue.isSelected()) {
operation = Operation.Multiplication;
}
});
tfLowest.setPrefWidth(46);
tfLowest.setOnAction(e -> {
getLowest(tfLowest);
if (lowest != null) {
tfHighest.requestFocus();
}
});
tfHighest.setPrefWidth(46);
tfHighest.setOnAction(e -> {
getHighest(tfHighest);
if (lowest != null) {
tfNumberOfProblems.requestFocus();
}
});
tfNumberOfProblems.setPrefWidth(46);
tfNumberOfProblems.setOnAction(e -> {
getProblemsNumber(tfNumberOfProblems);
if (number != null) {
bBegin.requestFocus();
}
});
bBegin.setStyle("-fx-background-color: blue; -fx-text-fill: white;");
bBegin.setOnAction(e -> {
getName(tfName);
if (name == null) {
return;
}
getLowest(tfLowest);
if (lowest == null) {
return;
}
getHighest(tfHighest);
if (highest == null) {
return;
}
getProblemsNumber(tfNumberOfProblems);
if (number == null) {
return;
}
Random random = new Random();
op1 = random.nextInt(highest - lowest + 1) + lowest;
op2 = random.nextInt(highest - lowest + 1) + lowest;
lCardTask.setText(op1 + " " + operation.toString() + " " + op2 + " =");
tfAnswer.requestFocus();
lScoreValue.setText(Integer.toString(taskScore));
lScorePctValue.setText(taskCounter == 0 ? "0.0" : Double.toString(100.0*taskCounter/taskCounter));
});
// Right Section
lCardTask.setFont(new Font(28));
tfAnswer.setPrefWidth(72);
tfAnswer.setOnAction(e -> {
if (taskCounter >= number) {
return;
}
int answ;
try {
answ = Integer.parseInt(tfAnswer.getText().trim());
}
catch (NumberFormatException ex) {
showErrorAlert("Can not read response");
return;
}
int correct = operation.make(op1, op2);
if (correct == answ) {
taskScore++;
lCheck.setText("Correct!");
}
else {
lCheck.setText("Incorrect...");
}
taskCounter++;
lScoreValue.setText(Integer.toString(taskScore));
lScorePctValue.setText(taskCounter == 0 ? "0.0" : Double.toString(100.0*taskScore/taskCounter));
if (taskCounter >= number) {
bPlayAgain.setDisable(false);
bPlayAgain.requestFocus();
lCardTask.setText("");
lCheck.setText("");
}
else {
tfAnswer.setText("");
bBegin.fire();
}
});
lCheck.setFont(new Font(28));
bPlayAgain.setStyle("-fx-background-color: green; -fx-text-fill: white;");
bPlayAgain.setDisable(true);
bPlayAgain.setOnAction(e -> {
taskCounter = 0;
taskScore = 0;
bBegin.fire();
});
// Bottom Section
// Required statements for JavaFX
Scene scene = new Scene(pane, 550, 450);
stage.setScene(scene);
stage.show();
}
private void getName(TextField tfName) {
if (tfName.getText().trim().isEmpty()) {
showErrorAlert("Empty name");
name = null;
}
else {
name = tfName.getText().trim();
}
}
private void getLowest(TextField tfLowest) {
try {
int lf = Integer.parseInt(tfLowest.getText());
if (highest != null && lf > highest) {
throw new IllegalArgumentException();
}
lowest = lf;
}
catch (Exception e) {
showErrorAlert("Invalid value for lowest factor");
lowest = null;
}
}
private void getHighest(TextField tfHighest) {
try {
int hf = Integer.parseInt(tfHighest.getText());
if (lowest != null && hf < lowest) {
throw new IllegalArgumentException();
}
highest = hf;
}
catch (Exception e) {
showErrorAlert("Invalid value for highest factor");
highest = null;
}
}
private void getProblemsNumber(TextField tfNumber) {
try {
int np = Integer.parseInt(tfNumber.getText());
if (np <= 0) {
throw new IllegalArgumentException();
}
number = np;
}
catch (Exception e) {
showErrorAlert("Invalid value for highest factor");
number = null;
}
}
private void showErrorAlert(String s) {
Alert alert = new Alert(Alert.AlertType.ERROR);
alert.setTitle("Error!");
alert.setHeaderText(s);
alert.setContentText(null);
alert.showAndWait();
}
/**
* Main driver method of the application
*
* @param args command line arguments
*/
public static void main(String[] args) {
launch(args);
}
}