Trying to do a JTable which adds data from a JTextField

Introduction

Oracle has a helpful tutorial, Creating a GUI With Swing. Skip the Learning Swing with the NetBeans IDE section.

I created the following GUI.

JTable Example 1

Here’s the same GUI after adding a couple of students.

JTable Example 2

Explanation

The model–view–controller (MVC) pattern is useful when creating a Swing application. The name implies that you create the model first, then the view, then the controller.

An application model is made up of one or more plain Java getter/setter classes.

A Swing view is one JFrame with one or more JPanels. The view displays the contents of the model. The view does not modify the model.

Each Swing ActionListener is a controller. The controllers update the model.

Model

I created two model classes. The Student class holds a name, age, and class.

The JTableModel class holds the DefaultTableModel for the JTable.

View

All Swing applications must start with a call to the SwingUtilities invokeLater method. This method ensures that all Swing components are created and executed on the Event Dispatch Thread.

I created a JFrame and two JPanels. One JPanel holds the JTable and the other JPanel holds the add student form. The JFrame has a default BorderLayout. I placed the table JPanel in the center and the form JPanel on the east side.

The table JPanel uses a BorderLayout. The JTable is placed inside of a JScrollPane. The JScrollPane is placed inside of the table JPanel in the center.

The form JPanel uses a GridBagLayout to create a form structure JPanel.

Complete explanations of all the Swing layout managers can be found in the Oracle tutorial.

Controller

The anonymous JButton ActionListener checks to see if the fields have been typed. If so, a Student instance is created and passed to the application model. If not, an error display pops up.

Code

Here’s the complete runnable code. I made the additional classes inner classes so I could post the code as one block.

import java.awt.BorderLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.table.DefaultTableModel;

public class JTableExample implements Runnable {

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new JTableExample());
    }
    
    private final JTableModel model;
    
    private JFrame frame;
    
    private JTextField nameField, ageField, classField;
    
    public JTableExample() {
        this.model = new JTableModel();
    }

    @Override
    public void run() {
        frame = new JFrame("JTable Example");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        
        frame.add(createTablePanel(), BorderLayout.CENTER);
        frame.add(createAddPanel(), BorderLayout.EAST);
        
        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
    }
    
    private JPanel createTablePanel() {
        JPanel panel = new JPanel(new BorderLayout());
        panel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
        
        JTable table = new JTable(model.getTableModel());
        JScrollPane scrollPane = new JScrollPane(table);
        
        panel.add(scrollPane, BorderLayout.CENTER);
        
        return panel;
    }
    
    private JPanel createAddPanel() {
        JPanel panel = new JPanel(new GridBagLayout());
        panel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
        
        GridBagConstraints gbc = new GridBagConstraints();
        gbc.anchor = GridBagConstraints.LINE_START;
        gbc.fill = GridBagConstraints.HORIZONTAL;
        gbc.insets = new Insets(0, 5, 5, 5);
        gbc.gridwidth = 1;
        gbc.gridx = 0;
        gbc.gridy = 0;
        
        JLabel label = new JLabel("Name:");
        panel.add(label, gbc);
        
        gbc.gridx++;
        nameField = new JTextField(20);
        panel.add(nameField, gbc);
        
        gbc.gridx = 0;
        gbc.gridy++;
        label = new JLabel("Age:");
        panel.add(label, gbc);
        
        gbc.gridx++;
        ageField = new JTextField(20);
        panel.add(ageField, gbc);
        
        gbc.gridx = 0;
        gbc.gridy++;
        label = new JLabel("Class:");
        panel.add(label, gbc);
        
        gbc.gridx++;
        classField = new JTextField(20);
        panel.add(classField, gbc);
        
        gbc.gridwidth = 2;
        gbc.gridx = 0;
        gbc.gridy++;
        JButton button = new JButton("Add Student");
        button.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent event) {
                String name = nameField.getText().trim();
                String ageString = ageField.getText().trim();
                String level = classField.getText().trim();
                
                if (name.isEmpty() || ageString.isEmpty() || level.isEmpty()) {
                    JOptionPane.showMessageDialog(
                            frame, "Please enter all information");
                    return;
                }
                
                int age = getAge(ageString);
                if (age > 0) {
                    model.addStudent(new Student(name, age, level));
                    clearInputFields();
                }
            }

            private int getAge(String ageString) {
                int age = -1;
                try {
                    age = Integer.valueOf(ageString);
                } catch (NumberFormatException e) {
                    JOptionPane.showMessageDialog(
                            frame, "Please enter a numeric age");
                }
                return age;
            }

            private void clearInputFields() {
                nameField.setText("");
                ageField.setText("");
                classField.setText("");
                
                nameField.requestFocus();
            }
        });
        
        panel.add(button, gbc);
        frame.getRootPane().setDefaultButton(button);
        
        return panel;
    }
    
    public class JTableModel {
        
        private final DefaultTableModel tableModel;
        
        public JTableModel() {
            this.tableModel = new DefaultTableModel();
            tableModel.addColumn("Name");
            tableModel.addColumn("Age");
            tableModel.addColumn("Class");
        }
        
        public void addStudent(Student student) {
            Object[] rowData = new Object[3];
            rowData[0] = student.getName();
            rowData[1] = student.getAge();
            rowData[2] = student.getLevel();
            tableModel.addRow(rowData);
        }

        public DefaultTableModel getTableModel() {
            return tableModel;
        }
        
    }
    
    public class Student {
        
        private final int age;
        
        private final String level, name;

        public Student(String name, int age, String level) {
            this.name = name;
            this.age = age;
            this.level = level;
        }

        public int getAge() {
            return age;
        }

        public String getLevel() {
            return level;
        }

        public String getName() {
            return name;
        }
        
    }

}