A minimal text editor
Enough of an application to meet every part of a Swing program at once.
A text editor is the traditional first real Swing application because it needs a component, a menu, file I/O, and state that has to stay in step — without needing any domain logic.
The shape
JTextArea area = new JTextArea();
frame.add(new JScrollPane(area));
The scroll pane matters. Adding the text area directly gives you an editor that cannot scroll, and the symptom — text disappearing past the bottom edge — looks like a bug in the component.
Files
private void open(Path p) throws IOException {
area.setText(Files.readString(p));
area.setCaretPosition(0);
current = p;
modified = false;
}
private void save(Path p) throws IOException {
Files.writeString(p, area.getText());
current = p;
modified = false;
}
setCaretPosition(0) is the small detail that makes it feel right — without it the view stays wherever it was.
Reading a whole file into memory is fine for an editor of this kind and wrong for large files. That limit is worth being explicit about rather than discovering.
The file chooser
JFileChooser chooser = new JFileChooser();
if (chooser.showOpenDialog(frame) == JFileChooser.APPROVE_OPTION) {
open(chooser.getSelectedFile().toPath());
}
Always check the return value. Assuming the user pressed Open gives you a NullPointerException the first time somebody cancels.
Tracking changes
area.getDocument().addDocumentListener(new DocumentListener() {
public void insertUpdate(DocumentEvent e) { modified = true; }
public void removeUpdate(DocumentEvent e) { modified = true; }
public void changedUpdate(DocumentEvent e) { modified = true; }
});
Listen to the document, not the component — that is where edits actually happen, and it is Swing’s model-view separation showing through.
Then refuse to lose work:
if (modified) {
int r = JOptionPane.showConfirmDialog(frame, "Save changes?");
if (r == JOptionPane.CANCEL_OPTION) return;
if (r == JOptionPane.YES_OPTION) save(current);
}
Handling all three answers — including cancel meaning “do nothing at all” — is where most first attempts are wrong.
Encoding
Files.readString uses UTF-8. Older code using FileReader picked up the platform default, so a file written on one machine could be unreadable on another. Being explicit about encoding is not optional in anything that will be shared.