Lesson 22 of 25
Java Swing GUI Development
Build desktop interfaces with windows, labels, text fields, buttons, layouts, tables, and event handlers.
Learning objectives
- Explain the role of
JFrame,JPanel, and Swing components. - Arrange components with layout managers.
- Respond to button clicks using action listeners.
- Read values from text fields and display validation messages.
- Populate a
JTablewith tabular data. - Build a small student-entry desktop application.
1. How Swing applications are structured
Swing is Java's traditional desktop GUI toolkit. A typical application uses a JFrame as the main window, one or more JPanel containers, and controls such as JLabel, JTextField, JButton, and JTable.
Example: first Swing window
import javax.swing.*;
public class FirstWindow {
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
JFrame frame = new JFrame("My First Swing App");
frame.setDefaultCloseOperation(
JFrame.EXIT_ON_CLOSE
);
frame.setSize(420, 200);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
});
}
}
SwingUtilities.invokeLater starts the interface on Swing's Event Dispatch Thread (EDT), which is the correct thread for creating and updating Swing components.
2. Adding components with a layout manager
A layout manager controls component positioning. BorderLayout, FlowLayout, and GridLayout are useful beginner layouts.
import javax.swing.*;
import java.awt.*;
public class StudentForm {
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
JFrame frame = new JFrame("Student Form");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel form = new JPanel(new GridLayout(3, 2, 8, 8));
JTextField txtName = new JTextField();
JTextField txtMark = new JTextField();
JButton btnCheck = new JButton("Check Result");
form.add(new JLabel("Student Name:"));
form.add(txtName);
form.add(new JLabel("Mark:"));
form.add(txtMark);
form.add(new JLabel());
form.add(btnCheck);
frame.add(form);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
});
}
}
3. Handling button clicks
Swing is event-driven. The program waits for an event—such as a button click—and then invokes the registered listener.
Example: validate and calculate
btnCheck.addActionListener(event -> {
String name = txtName.getText().trim();
try {
int mark = Integer.parseInt(
txtMark.getText().trim()
);
if (name.isBlank()) {
JOptionPane.showMessageDialog(
frame,
"Please enter the student's name."
);
return;
}
if (mark < 0 || mark > 100) {
JOptionPane.showMessageDialog(
frame,
"Mark must be from 0 to 100."
);
return;
}
String result = mark >= 50 ? "Pass" : "Fail";
JOptionPane.showMessageDialog(
frame,
name + " - " + result
);
} catch (NumberFormatException ex) {
JOptionPane.showMessageDialog(
frame,
"Mark must be a whole number."
);
}
});
4. Displaying tabular data with JTable
JTable displays rows and columns. For dynamic data, DefaultTableModel is convenient for beginner applications.
import javax.swing.*;
import javax.swing.table.DefaultTableModel;
String[] columns = {"Student ID", "Name", "Mark"};
DefaultTableModel model =
new DefaultTableModel(columns, 0);
model.addRow(new Object[]{"S001", "Amina", 82});
model.addRow(new Object[]{"S002", "Daniel", 74});
JTable table = new JTable(model);
JScrollPane scrollPane = new JScrollPane(table);
Mini project: Student Result GUI
The following example combines fields, validation, a button event, and a table.
import javax.swing.*;
import javax.swing.table.DefaultTableModel;
import java.awt.*;
public class StudentResultApp extends JFrame {
private final JTextField txtId = new JTextField();
private final JTextField txtName = new JTextField();
private final JTextField txtMark = new JTextField();
private final DefaultTableModel model =
new DefaultTableModel(
new String[]{"ID", "Name", "Mark", "Result"},
0
);
public StudentResultApp() {
setTitle("Student Result App");
setDefaultCloseOperation(EXIT_ON_CLOSE);
JPanel form = new JPanel(new GridLayout(4, 2, 8, 8));
form.add(new JLabel("Student ID:"));
form.add(txtId);
form.add(new JLabel("Name:"));
form.add(txtName);
form.add(new JLabel("Mark:"));
form.add(txtMark);
JButton btnAdd = new JButton("Add Student");
form.add(new JLabel());
form.add(btnAdd);
JTable table = new JTable(model);
btnAdd.addActionListener(event -> addStudent());
add(form, BorderLayout.NORTH);
add(new JScrollPane(table), BorderLayout.CENTER);
setSize(600, 350);
setLocationRelativeTo(null);
}
private void addStudent() {
String id = txtId.getText().trim();
String name = txtName.getText().trim();
try {
int mark = Integer.parseInt(
txtMark.getText().trim()
);
if (id.isBlank() || name.isBlank()) {
throw new IllegalArgumentException(
"ID and name are required."
);
}
if (mark < 0 || mark > 100) {
throw new IllegalArgumentException(
"Mark must be from 0 to 100."
);
}
String result = mark >= 50 ? "Pass" : "Fail";
model.addRow(
new Object[]{id, name, mark, result}
);
txtId.setText("");
txtName.setText("");
txtMark.setText("");
} catch (NumberFormatException ex) {
JOptionPane.showMessageDialog(
this,
"Mark must be a whole number."
);
} catch (IllegalArgumentException ex) {
JOptionPane.showMessageDialog(
this,
ex.getMessage()
);
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
new StudentResultApp().setVisible(true);
});
}
}
Common mistakes
| Problem | Why it happens | Fix |
|---|---|---|
| GUI freezes during a long task | Long work is running on the Event Dispatch Thread. | Move long-running work to a background worker such as SwingWorker. |
| Components overlap or resize badly | Absolute positioning or an unsuitable layout was used. | Use layout managers instead of hard-coded coordinates. |
| Input crashes the event handler | Text is converted without validation. | Validate fields and catch NumberFormatException. |
Summary
You can now construct a Swing interface, react to user events, validate input, and display data in a table. Lesson 23 connects Java to SQLite through JDBC so application data can persist after the program closes.