Skip to Content
Course content

232: Building a Simple Text Editor with Swing

Click on the "Edit" button in the top corner of the screen to edit your slide content.

When people first dive into building a text editor in Swing, I usually see them start with a KeyListener. They think, "Okay, if I want to make an editor, I need to listen for every single key the user presses and manually append that character to a string or a buffer." It feels intuitive, but it's actually a trap.

The "KeyListener" Trap: Why Manual Input Tracking Fails

If you try to build your editor by overriding keyPressed(), you'll quickly realize you've signed up for a world of pain. First, you'll miss events. What happens when a user right-clicks and selects "Paste" from the system menu? No key was pressed, so your KeyListener sees nothing, and your internal buffer stays empty while the screen shows text. Or consider different keyboard layouts and IMEs (Input Method Editors) used for languages like Japanese or Chinese; those don't map one-to-one with simple key events.

In the professional world, we don't reinvent the wheel for basic text entry. Swing already provides a highly optimized engine for this: the JTextArea.

Leveraging JTextArea and JScrollPane for Actual Functionality

The JTextArea isn't just a box; it's a sophisticated component that handles the cursor position, text selection, and the underlying document model for you. Your job as the engineer isn't to manage the characters, but to manage the container and the actions.

One mistake I see even experienced devs make is adding a JTextArea directly to a JFrame. Do that, and the moment your user types more lines than the window height, the text simply disappears off the bottom of the screen. You have to wrap the text area in a JScrollPane. This adds the vertical and horizontal scrollbars automatically when the content exceeds the visible area.

Here is how I would structure a bare-bones editor. Notice how I'm not worrying about individual keys; I'm focusing on the layout and the menu actions:

import javax.swing.*;
import java.awt.*;
import java.io.*;

public class SimpleTextEditor extends JFrame {
    private JTextArea textArea;

    public SimpleTextEditor() {
        setTitle("Engineer's Notepad");
        setSize(800, 600);
        setDefaultCloseOperation(EXIT_ON_CLOSE);

        // The engine: JTextArea
        textArea = new JTextArea();
        textArea.setFont(new Font("Monospaced", Font.PLAIN, 14));

        // The wrapper: JScrollPane is non-negotiable for editors
        JScrollPane scrollPane = new JScrollPane(textArea);
        add(scrollPane);

        createMenuBar();
    }

    private void createMenuBar() {
        JMenuBar menuBar = new JMenuBar();
        JMenu fileMenu = new JMenu("File");

        JMenuItem saveItem = new JMenuItem("Save");
        saveItem.addActionListener(e -> saveFile());

        fileMenu.add(saveItem);
        menuBar.add(fileMenu);
        setJMenuBar(menuBar);
    }

    private void saveFile() {
        JFileChooser fileChooser = new JFileChooser();
        if (fileChooser.showSaveDialog(this) == JFileChooser.APPROVE_OPTION) {
            try (PrintWriter out = new PrintWriter(fileChooser.getSelectedFile())) {
                out.println(textArea.getText());
                JOptionPane.showMessageDialog(this, "File saved successfully!");
            } catch (IOException ex) {
                JOptionPane.showMessageDialog(this, "Error saving file", "Error", JOptionPane.ERROR_MESSAGE);
            }
        }
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> {
            new SimpleTextEditor().setVisible(true);
        });
    }
}

I used SwingUtilities.invokeLater in the main method because Swing is not thread-safe. If you're updating the UI from a background thread (like when loading a massive file), you'll run into weird, non-deterministic crashes if you don't push those updates to the Event Dispatch Thread (EDT). It's a small detail that separates the amateurs from the pros.




📋 Practical Task

Implement a Real-Time Word Counter

In the SimpleTextEditor code provided in the lesson, the editor is static—it doesn't provide any feedback to the user about the document status. Your task is to add a "Status Bar" to the bottom of the window that displays a live word count.

  • The Requirement: Add a JLabel at the bottom of the frame (use a BorderLayout.SOUTH position) that displays: "Words: X".
  • The Challenge: Since we aren't using a KeyListener, you need to find a way to detect when the text changes. Research and implement a DocumentListener attached to the textArea.getDocument().
  • The Logic: The word count should update every time a character is inserted, removed, or changed. A simple way to count words is to split the string by whitespace: textArea.getText().trim().split("\\s+").length (be sure to handle the case where the text area is empty so you don't get a count of 1 for an empty string).
Rating
0 0

There are no comments for now.

to be the first to leave a comment.