Tóm Tắt
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.
Here’s the same GUI after adding a couple of students.
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;
}
}
}