【Swingアプリ開発】メモ帳アプリの解答例

2025-08-06

以下は、Swingを使用した基本的なメモ帳アプリケーションの完全な実装例です。ファイルの新規作成、開く、保存、終了機能と基本的なテキスト編集機能を備えています。

import javax.swing.*;
import javax.swing.filechooser.FileNameExtensionFilter;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.io.*;

public class SimpleTextEditor {
    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> {
            // メインウィンドウの作成
            JFrame frame = new JFrame("シンプルメモ帳");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.setSize(800, 600);

            // テキスト編集領域
            JTextArea textArea = new JTextArea();
            textArea.setFont(new Font("Meiryo", Font.PLAIN, 14));
            JScrollPane scrollPane = new JScrollPane(textArea);
            frame.add(scrollPane, BorderLayout.CENTER);

            // メニューバーの作成
            JMenuBar menuBar = new JMenuBar();

            // ファイルメニュー
            JMenu fileMenu = new JMenu("ファイル");

            JMenuItem newItem = new JMenuItem("新規作成");
            JMenuItem openItem = new JMenuItem("開く...");
            JMenuItem saveItem = new JMenuItem("保存...");
            JMenuItem saveAsItem = new JMenuItem("名前を付けて保存...");
            JMenuItem exitItem = new JMenuItem("終了");

            // 編集メニュー
            JMenu editMenu = new JMenu("編集");

            JMenuItem cutItem = new JMenuItem("切り取り");
            JMenuItem copyItem = new JMenuItem("コピー");
            JMenuItem pasteItem = new JMenuItem("貼り付け");

            // メニュー項目をメニューに追加
            fileMenu.add(newItem);
            fileMenu.add(openItem);
            fileMenu.addSeparator();
            fileMenu.add(saveItem);
            fileMenu.add(saveAsItem);
            fileMenu.addSeparator();
            fileMenu.add(exitItem);

            editMenu.add(cutItem);
            editMenu.add(copyItem);
            editMenu.add(pasteItem);

            // メニューをメニューバーに追加
            menuBar.add(fileMenu);
            menuBar.add(editMenu);

            // フレームにメニューバーを設定
            frame.setJMenuBar(menuBar);

            // 現在編集中のファイル
            File currentFile = null;

            // アクションの実装
            newItem.addActionListener(e -> {
                textArea.setText("");
                currentFile = null;
                frame.setTitle("シンプルメモ帳");
            });

            openItem.addActionListener(e -> {
                JFileChooser fileChooser = new JFileChooser();
                fileChooser.setFileFilter(new FileNameExtensionFilter("テキストファイル (*.txt)", "txt"));

                if (fileChooser.showOpenDialog(frame) == JFileChooser.APPROVE_OPTION) {
                    currentFile = fileChooser.getSelectedFile();
                    frame.setTitle("シンプルメモ帳 - " + currentFile.getName());

                    try (BufferedReader reader = new BufferedReader(new FileReader(currentFile))) {
                        StringBuilder content = new StringBuilder();
                        String line;
                        while ((line = reader.readLine()) != null) {
                            content.append(line).append("\n");
                        }
                        textArea.setText(content.toString());
                    } catch (IOException ex) {
                        JOptionPane.showMessageDialog(frame, 
                            "ファイルを開けませんでした", 
                            "エラー", 
                            JOptionPane.ERROR_MESSAGE);
                    }
                }
            });

            Action saveAction = new AbstractAction() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    if (currentFile == null) {
                        // 名前を付けて保存を実行
                        JFileChooser fileChooser = new JFileChooser();
                        fileChooser.setFileFilter(new FileNameExtensionFilter("テキストファイル (*.txt)", "txt"));

                        if (fileChooser.showSaveDialog(frame) == JFileChooser.APPROVE_OPTION) {
                            currentFile = fileChooser.getSelectedFile();
                            if (!currentFile.getName().endsWith(".txt")) {
                                currentFile = new File(currentFile.getAbsolutePath() + ".txt");
                            }
                            frame.setTitle("シンプルメモ帳 - " + currentFile.getName());
                            saveToFile();
                        }
                    } else {
                        saveToFile();
                    }
                }

                private void saveToFile() {
                    try (BufferedWriter writer = new BufferedWriter(new FileWriter(currentFile))) {
                        writer.write(textArea.getText());
                    } catch (IOException ex) {
                        JOptionPane.showMessageDialog(frame, 
                            "ファイルを保存できませんでした", 
                            "エラー", 
                            JOptionPane.ERROR_MESSAGE);
                    }
                }
            };

            saveItem.setAction(saveAction);
            saveAsItem.addActionListener(e -> {
                currentFile = null;
                saveAction.actionPerformed(e);
            });

            exitItem.addActionListener(e -> System.exit(0));

            // 編集メニューのアクション
            cutItem.addActionListener(e -> textArea.cut());
            copyItem.addActionListener(e -> textArea.copy());
            pasteItem.addActionListener(e -> textArea.paste());

            // ショートカットキーの設定
            newItem.setAccelerator(KeyStroke.getKeyStroke("control N"));
            openItem.setAccelerator(KeyStroke.getKeyStroke("control O"));
            saveItem.setAccelerator(KeyStroke.getKeyStroke("control S"));
            saveAsItem.setAccelerator(KeyStroke.getKeyStroke("control shift S"));

            cutItem.setAccelerator(KeyStroke.getKeyStroke("control X"));
            copyItem.setAccelerator(KeyStroke.getKeyStroke("control C"));
            pasteItem.setAccelerator(KeyStroke.getKeyStroke("control V"));

            frame.setVisible(true);
        });
    }
}

このメモ帳アプリの特徴

  1. 基本機能:
  • ファイル操作: 新規作成、開く、保存、名前を付けて保存
  • テキスト編集: 切り取り、コピー、貼り付け
  • 終了機能
  1. UI構成:
  • メニューバーに各種機能を配置
  • スクロール可能なテキスト編集領域
  • ファイルダイアログを使用したファイル操作
  1. 便利な機能:
  • キーボードショートカットのサポート
  • 編集中のファイル名をタイトルバーに表示
  • テキストファイルフィルタの適用

拡張可能なポイント

この基本実装をさらに発展させるためのアイデア:

  1. 追加機能:
  • 検索/置換機能
  • フォント設定の変更
  • 印刷機能
  • アンドゥ/リドゥ機能
  1. UI改善:
  • ツールバーの追加
  • ステータスバー(行数、文字数表示)
  • タブによる複数ファイル編集
  1. コードの改良:
  • コントローラクラスの導入(MVCパターン)
  • 最近使ったファイルリストの管理
  • 設定の永続化(Preferences APIの使用)

例えば、フォント変更機能を追加するには:

// メニューにフォント項目を追加
JMenu formatMenu = new JMenu("書式");
JMenuItem fontItem = new JMenuItem("フォント...");
formatMenu.add(fontItem);
menuBar.add(formatMenu);

// フォントダイアログの実装
fontItem.addActionListener(e -> {
    Font currentFont = textArea.getFont();
    FontDialog fontDialog = new FontDialog(frame, currentFont);
    fontDialog.setVisible(true);

    if (fontDialog.isApproved()) {
        textArea.setFont(fontDialog.getSelectedFont());
    }
});

// FontDialogクラスの簡易実装
class FontDialog extends JDialog {
    private boolean approved = false;
    private Font selectedFont;

    public FontDialog(Frame owner, Font initialFont) {
        super(owner, "フォントの選択", true);
        setSize(300, 200);

        // フォント選択UIの実装...
        // サンプル実装(簡略化)
        JButton okButton = new JButton("OK");
        okButton.addActionListener(e -> {
            approved = true;
            selectedFont = initialFont; // 実際にはダイアログから選択したフォントを設定
            dispose();
        });

        JButton cancelButton = new JButton("キャンセル");
        cancelButton.addActionListener(e -> dispose());

        add(okButton, BorderLayout.SOUTH);
    }

    public boolean isApproved() { return approved; }
    public Font getSelectedFont() { return selectedFont; }
}

このメモ帳アプリは、Swingの基本的なコンポーネントとファイル操作、メニューシステムを理解するのに最適なサンプルです。基本機能を理解したら、段階的に機能を追加していくことをおすすめします。