The next example we are going to work is a system for serving up multiple choice quizzes to a group of students. The system is going to consist of three applications:
All three of these applications will interact with the same database.
I will be writing the code for the first and the third applications. You will be writing the code for the second application as your next homework assignment.
A quiz writing application
The first application is an application for creating quizzes and quiz questions.
The application consists of a single window and a dialog box.
There is a menu bar at the top of the window with File and Quizzes menus in it. The File menu only has a single item, a Quit command. The Quizzes menu contains two items, one to make a new quiz and another to remove the currently selected quiz from the database.
Below the menu bar is a ChoiceBox that displays a list of quiz titles. When the user selects a quiz from the ChoiceBox the application will display the questions for that particular quiz in the list view.
Below the ListView we have three buttons used to make new questions, edit an existing question, or delete the selected question. Clicking either the New or Edit buttons will bring up a dialog that the user can use to enter the details of a question.
All of the quiz questions will be multiple choice questions with four possible answers. We will enter the four possible choices as a comma separated list of options. When setting up the question we will also record which of the options is correct by using the letters a through d.
Since this application uses a number of ideas that I have already demonstrated in the Hotel example, I am going to limit my comments here to some special features that I want to draw your attention to.
The first special feature is the ChoiceBox that displays the list of quizzes in the system.
The code that initializes that ChoiceBox appears in the initialize method for the main window's controller.
@Override public void initialize(URL url, ResourceBundle rb) { dao = new QuizDAO(); ArrayList<String> quizNames = dao.getQuizNames(); String quiz = quizNames.get(0); quizChoice.getItems().addAll(quizNames); quizChoice.setValue(quiz); quizChoice.getSelectionModel().selectedItemProperty().addListener((observable, oldValue, newValue)->changeQuiz(newValue)); dao.setQuiz(quiz); subjectsList.setItems(dao.getSubjects()); }
An important thing going on here is the change listener I attached to the ChoiceBox. Whenever the user selects a new quiz from the list we will call a changeQuiz() method to update things appropriately:
private void changeQuiz(Object quiz) { if(quiz != null) dao.setQuiz(quiz.toString()); }
This method in turn calls a method in the DAO class that changes the currently selected quiz:
private String subjectsSQL = "select id, subject from questions where quiz=?"; private PreparedStatement subjectsStmt; private PreparedStatement questionStmt; private String quizIDSQL = "select id from quizzes where title=?"; private PreparedStatement quizIDStmt; public void setQuiz(String quizName) { try { quizIDStmt.setString(1, quizName); ResultSet result = quizIDStmt.executeQuery(); if(result.next()) { currentQuiz = result.getInt(1); } else currentQuiz = 0; }catch (SQLException ex) { currentQuiz = 0; ex.printStackTrace(); } if(currentQuiz == 0) return; rebuildSubjects(); } public void rebuildSubjects() { subjects.clear(); try { subjectsStmt.setInt(1, currentQuiz); ResultSet resultSet = subjectsStmt.executeQuery(); while (resultSet.next()) { int id = resultSet.getInt("id"); String subject = resultSet.getString("subject"); subjects.add(new Subject(id,subject)); } } catch (SQLException ex) { ex.printStackTrace(); } }
Another special feature to pay attention to is the code linked to the item in the Quizzes menu for making a new quiz. As part of the process of making a new quiz we need to ask the user to enter a name for the quiz. To handle that we use prebuilt dialog that JavaFX provides, the TextInputDialog.
@FXML private void newQuiz(ActionEvent event) { TextInputDialog dialog = new TextInputDialog(); dialog.setHeaderText(null); dialog.setGraphic(null); dialog.setTitle("New Quiz"); dialog.setContentText("Enter a quiz name:"); Optional<String> result = dialog.showAndWait(); if (result.isPresent()){ String quiz = result.get(); dao.addQuiz(quiz); quizChoice.getItems().clear(); ArrayList<String> quizNames = dao.getQuizNames(); quizChoice.getItems().addAll(quizNames); quizChoice.setValue(quiz); dao.setQuiz(quiz); } }
To use a TextInputDialog we set some options for the dialog, such as its title and a prompt for the question we are asking, and then call the showAndWait()
method to display the dialog. The resulting dialog looks like this:
The TextInputDialog will return a String to us with the text that the user entered. One complication is that the user has the option of canceling the dialog and not providing an answer. To cover that case the TextInputDialog's showAndWait()
method returns a special Optional<String>
object. We can ask that object whether or not the user supplied an answer by calling the Optional's isPresent()
method. If the answer to that question is "yes" we can get the actual String the user entered by then calling the Optional's get()
method.