You can connect an event to a handler, keep slow work off the Swing event-dispatch thread, use exceptions at meaningful boundaries, and read/write text with automatic resource cleanup. Readiness: classes, interfaces, lambdas or anonymous handlers.
In sequential code, the program chooses the next operation. In a GUI, the framework dispatches user/system events and calls registered handlers. Swing components should be created and updated on the event-dispatch thread (EDT); long file/database/network work on that thread freezes the interface.
SwingUtilities.invokeLater(() -> {
JFrame frame = new JFrame("Course Notes");
JButton save = new JButton("Save");
JLabel status = new JLabel("Ready");
save.addActionListener(event -> status.setText("Save requested"));
frame.add(save, BorderLayout.CENTER);
frame.add(status, BorderLayout.SOUTH);
frame.pack();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
});
Use exceptions to report conditions a caller cannot handle through a normal result. Catch at a boundary that can add context or recover; do not swallow an exception. Try-with-resources closes files even when processing fails.
static List<String> readNotes(Path path) throws IOException {
try (BufferedReader reader = Files.newBufferedReader(path, StandardCharsets.UTF_8)) {
return reader.lines().toList();
}
}
If a chosen file is missing, readNotes throws IOException. The UI boundary catches it, records controlled diagnostic detail, and shows “Could not open this file.” It must not show a stack trace as the user message or pretend the list is empty.
Code catches Exception and does nothing. Hint: can the caller distinguish success? Solution: catch the narrow expected type where recovery is possible; otherwise propagate with context. Log once at the handling boundary, not at every layer.
Build a small Swing notes viewer with Open and Save buttons, a text area, status text, and UTF-8 files. Use a file chooser; handle cancel, missing/unreadable file, and save failure. Keep large file work off the EDT and return UI updates to the EDT. A console version is an allowed prerequisite step, not a replacement for the GUI outcome.
Q1 Who calls a registered GUI handler? The event-dispatch framework. Q2 Why avoid slow EDT work? It blocks repaint/input. Q3 Why narrow catches? Preserve meaning and avoid hiding unrelated defects. Q4 Why try-with-resources? Reliable cleanup.
Add recent-file history stored as UTF-8. Define file format, recovery from one malformed line, atomic-save strategy, and tests. Rubric: event behavior 2, file correctness 3, exception strategy 2, non-blocking UI 2, tests 1.
Event source -> dispatch -> handler -> state/UI change. Resource acquisition and cleanup must remain correct on both success and failure.