Java Practice: Tiny Student Management System Based on Swing

Last several days I have been learning JDBC and how to use Swing to build GUI. As a test, I build a small and basic Student Management System to help myself understand the concepts of Software Engineering. Each student is an entry in the data, includes properties below:

Here are the functions of the system:

  1. Click the Add button and a JDialog will appear, where we can add new students to the database. If the operation is successful, a Message Window pops up.
  2. Provide a Delete button. Click the delete button to delete the selected row and refresh the data in the table. If no row is selected when you click delete, you will be prompted with “select a row before deleting”
  3. Provide an Modify button. When clicked, a JDialog pops up to display the selected data and it can be modified. If the operation is successful, a Message Window pops up. If no row is selected when clicking, you will be prompted “please select a row of data before editing”.
  4. Four buttons appear below: Home Page, Previous Page, Next Page, Last Page
    • Only 6 pieces of data are displayed in the table.
    • On the last page, it should be noted that if the total number in the database can be divided by 6, then 6 students will be displayed on the last page, otherwise the remainder divided by 6 will not be displayed. For example, if there are 20 students in total, 2 students will be displayed on the last page.
    • Button status requirements: If there is data on the next page, you can click the next page, otherwise the next page button is unavailable. The same is true for first page, previous page and last page.
  5. Paging with drop-down boxes.

At first, to get familiar with the components of Java Swing, I wrote a very very supid one single main method version. It just works (Todd Howard’s tone). The code is here.

So when the interface code becomes complex, it could be a problem. The code only used to write the interface will be very long, poor readability, difficult to maintain, and there are various anonymous internal classes, which is very difficult to locate. For example, to add JPanel for displaying various functional interfaces and add listeners to each button, the code will become very lengthy and difficult to read. For example, this is the anonymous internal class of listener for Add button :

bAdd.addActionListener(new ActionListener() {
    public void actionPerformed(ActionEvent e) {
        // Instantiate jDialog from an external frame
        JDialog d = new JDialog(f);
        // Set modal
        d.setModal(true);

        d.setTitle("Add");
        d.setSize(400, 300);
        d.setLocation(200, 200);
        d.setLayout(new BorderLayout());

        // Add a panel to place the name, input box and submit button
        JPanel p = new JPanel();

        final JLabel lName = new JLabel("Name");
        final JTextField tfName = new JTextField("");
        final JLabel lHp = new JLabel("Hp");
        final JTextField tfHp = new JTextField("");
        JButton bAddinAdd = new JButton("Submit");
        tfName.setPreferredSize(new Dimension(80, 30));
        tfHp.setPreferredSize(new Dimension(80, 30));

        p.add(lName);
        p.add(tfName);
        p.add(lHp);
        p.add(tfHp);
        p.add(bAddinAdd);
        d.add(p);

        // Add a listener to the submit button
        bAddinAdd.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                HeroDAO dao = new HeroDAO();
                Hero h = new Hero();
                h.name = tfName.getText();
                h.hp = Integer.parseInt(tfHp.getText());

                dao.add(h);
                htm.heros = dao.list();
                htm.updateInfo();
                htm.setPage(0);
                setb.setbutton();
                setb.setComboBox();

                t.updateUI();
                JOptionPane.showMessageDialog(f, "Submitted successfully");
            }
        });
        d.setVisible(true);
    }
});

In order to make the code more maintainable and avoid falling into the mud pit of lengthy code, we need to plan the code scientifically. Frame : The whole program has only one main frame, so put this class under the package frame. Panel : JFrame itself has a panel, and then each functional module has a panel, so plan these panels under panel. Listener : Make all listeners into independent classes, implement actionlistener interface, and put them under gui.listener package Model : Model is used to store data. StudentTableModel and StudentDAO will be used in this project, which are placed under the model package.

In this project, the main function of various button listeners is to obtain the value of the component and modify the value of the component. This involves how to access components in the listener.

So how to make it easy for listeners to get components? This requires two design methods :

  1. In the frame and panel classes, declare the components as public
  2. Design the frame and panel classes as single instance mode

For example, Add Panel only needs one instance, and there is no need to create a new instance every time the panel is displayed. Not only does it not need to, but it should not create new instances every time. Therefore, designing AddPanel in singleton mode can solve this problem.

public class AddPanel {
    private static final AddPanel instance = new AddPanel();
	
    public static AddPanel getInstance(){
        return instance;
    }
    
    private JDialog d = new JDialog(mainFrame.getFrame());

    public JDialog getPanel() { return d; }
}

There should be only one instance of this class. By privatizing its construction method, the external cannot get a new instance through new. A getInstance method of public static is provided. The external caller obtains the defined object through this method, and obtains the same object every time. So as to achieve the purpose of single case.

public class AddActionListener implements ActionListener {
    @Override
    public void actionPerformed(ActionEvent e) {
        AddPanel.getInstance().show();
    }
}

In this way, the listener can access the components through the panel of singleton mode. The code is much easier to maintain than using the traditional internal class method to add listeners directly in the main method and new JFrame.

The database in the project is built based on MySQL-5.5.15-win64. For JDBC, I used an external package mysql-connector-java-5.0.8. The code of whole project is here.