JavaScript week JavaScript week
This week up to 80% off on HTML/CSS and JavaScript courses.

Lesson 6 - Birthday Reminder in Java Swing - Wiring the layers

In the previous lesson, Birthday Reminder in Java Swing - Logic Layer, we finished the basis of the logic layer of our application. In today's tutorial, we're going to wire it to the form and make the application up and running.

Wiring the presentation and logic layers

Now we've both the presentation part of the application (forms) and the logic part (classes) ready. These 2 layers are strictly separated in applications. Otherwise, the code would be very confusing. You should never perform calculations, file manipulations, database queries, and similar things directly in the form code! We always create a class that provides the appropriate methods and we only use that class in the form. The logic stays in the class and the class shouldn't even know that the form exists. Therefore, for example, the class also shouldn't display any error messages but only throw exceptions in case of an error. It's the form what is responsible for displaying error messages to the user. The form is the part of the application that communicates with the user. No other does it.

If it crossed your mind that our simple calculator, which we created in first lessons of the course, was incorrectly designed, you're right. For the sake of simplicity, we've written the calculations directly into the button handling method. The right way would be having a class that computes the results, and we would then just call it from the form.

So now let's show how to do it right.

Wiring the presentation and logic

Let's move to the source code of the OverviewJFrame form and add a private attribute of the PersonManager type to the class. We'll initialize it with a new PersonManager instance:

private PersonManager personManager = new PersonManager();

The PersonManager instance is created when the form is created, and the form will then communicate with it to perform the tasks the user wants.

In the form's constructor, we'll set the todayJLabel to the current date and set the JList's model property to the PersonManager's model. That's how we bind the JList to the DefaultListModel. From now on, it'll show its contents and if something is added to the model, it'll also be reflected in the JList. If there's any person in the model, we'll set the selected JList item to the first index.

public OverviewJFrame() {
    initComponents();
    todayJLabel.setText(Date.format(LocalDate.now()));
    personsJList.setModel(personManager.getModel());
    if (!personManager.getPersons().isEmpty()) {
        personsJList.setSelectedIndex(0);
    }
}

Adding and removing people

It's time for us to finally see something, so we're going to add some people. First, we'll move to the code of the PersonJDialog. We'll add a private attribute of the Person type here and generate a getter for it. This is where we'll load the person data from when we'll open the dialog for the person the user has selected.

private Person person = null;

 public Person getPerson() {
    return person;
}

Now we'll click the OK button and create there a person based on the data that the user has entered. We'll save the person to a private attribute.

If anything fails, we'll display a MessageDialog with an error. You've already encountered a try-catch block that allows you to catch exceptions and somehow handle these errors instead of letting the application crash.

private void okJButtonActionPerformed(java.awt.event.ActionEvent evt) {
    try {
        LocalDate birthday = Date.parse(birthdayJFormattedTextField.getText());
        person = new Person(nameJTextField.getText(), birthday);
        dispose();
    } catch (ParseException | IllegalArgumentException ex) {
        JOptionPane.showMessageDialog(null, "Error: " + ex.getMessage());
    }
}

It's the line:

person = new Person(personJTextField.getText(), birthday);

which can throw an exception. As we throw the exception directly in the person's constructor in case of invalid input, you can check it there. Another exception can be caused by parsing the date, even if it actually never happens because of the JFormattedTextField. We placed the code which may throw an exception in the try block. Then we catch the exception in the catch block and display its message to the user. If everything goes smoothly, the program won't even get into the catch block. We usually throw exceptions in logic classes and then catch them in forms. Exceptions are described in more detail in the Exceptions in Java lesson. We use dispose() to close the current form.

We're done with this form so let's move back to the OverviewJFrame. This time, we'll open the design view and double-click the addJButton and removeJButton buttons.

private void addJButtonActionPerformed(java.awt.event.ActionEvent evt) {
    PersonJDialog personJDialog = new PersonJDialog(this, true);
    personJDialog.setLocationRelativeTo(null);
    personJDialog.setVisible(true);

    Person newPerson = personJDialog.getPerson();
    if (newPerson != null) {
        personManager.add(newPerson);
    }
}

In the addJButton's handling method, we create a new PersonJDialog instance. In its constructor, we set the parent form to the current OverviewJFrame instance (this) and the dialog as modal in the second parameter. When the dialog box is displayed using setVisible(true), it'll block the rest of the application. The app will only become active again if the dialog box is closed. This means that we won't be able to work with the main form until we confirm or close the dialog box. We usually do display dialogs like this to prevent the user from opening the same dialog multiple times. Although we wouldn't mind if the user was using the app while entering a new person and even opened another input dialog. We'll load the person from the dialog box and if there's any (the user confirmed the dialog by clicking the OK button and didn't cancel it), we add this person to the manager. Because we use ListModel, the person will be displayed in the form's JListimmediately.

The handling method of the removeJButton will look like this:

private void removeJButtonActionPerformed(java.awt.event.ActionEvent evt) {
    Person selected = (Person)personsJList.getSelectedValue();
    if (selected != null) {
        personManager.remove(selected);
    }
}

The condition that determines whether a JList item is selected is very important. As you can see, we get to the selected item via the getSelectedValue() property. The item is then cast to Person because it's of an Object type (this is to make the JList universal). We'll pass this person to the remove method on the manager. This method will also physically remove it from the ListModel.

You can now try the app to add and remove people. Every time you add someone, they will immediately appear in the JList thanks to bindings. The JList always shows what the object's toString() method returns. Thus, for persons, it displays their name.

Adding and Removing Items in JList in Java Swing

Next time, Birthday Reminder in Java Swing - Completing the logic, we'll add more methods to the application's logic layer to complete it.


 

 

Article has been written for you by David Capka
Avatar
Do you like this article?
No one has rated this quite yet, be the first one!
The author is a programmer, who likes web technologies and being the lead/chief article writer at ICT.social. He shares his knowledge with the community and is always looking to improve. He believes that anyone can do what they set their mind to.
Unicorn College The author learned IT at the Unicorn College - a prestigious college providing education on IT and economics.
Previous article
Birthday Reminder in Java Swing - Logic Layer
All articles in this section
Form applications in Java Swing
Thumbnail
Next article
Birthday Reminder in Java Swing - Completing the logic
Activities (2)

 

 

Comments

To maintain the quality of discussion, we only allow registered members to comment. Sign in. If you're new, Sign up, it's free.

No one has commented yet - be the first!