【プログラミングしてみよう66】JavaのGUIプログラミング入門(Swing)

Java

前回はSocket通信を使ったネットワークプログラミングを学びました。

今回は「Swing」を使ったGUIプログラミングについて解説します。 これまですべてターミナル上で動くプログラムを作ってきましたが、SwingはJavaに標準で組み込まれているGUIライブラリで、ウィンドウ・ボタン・テキストフィールドなどを使ったデスクトップアプリが作れます。

Swingの基本

Swingの主要なコンポーネント(部品)は以下の通りです。

JFrame       // ウィンドウ本体
JPanel       // 部品を配置するパネル(コンテナ)
JLabel       // テキストを表示するラベル
JButton      // クリックできるボタン
JTextField   // 1行のテキスト入力欄
JTextArea    // 複数行のテキスト入力欄
JList        // リスト表示
JScrollPane  // スクロール対応のコンテナ

SwingのGUIはイベント駆動モデルで動作します。ボタンがクリックされたら何かをする、というように「イベントが発生したら処理を実行する」という形で書きます。

サンプルコード(はじめてのウィンドウ)

ファイル作成

「Java54」フォルダに HelloWindow.java という名前でファイルを作成します

コード入力

以下のコードを入力します。

import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.SwingUtilities;
import java.awt.Font;

public class HelloWindow {
    public static void main(String[] args) {
        // GUIはイベントディスパッチスレッドで作成する
        SwingUtilities.invokeLater(() -> {
            JFrame frame = new JFrame("はじめてのSwing");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.setSize(400, 200);

            JLabel label = new JLabel("Hello, Swing!", JLabel.CENTER);
            label.setFont(new Font("SansSerif", Font.BOLD, 24));

            frame.add(label);
            frame.setLocationRelativeTo(null); // 画面中央に表示
            frame.setVisible(true);
        });
    }
}

コンパイル

javac HelloWindow.java

実行

java HelloWindow

ウィンドウが開き「Hello, Swing!」と表示されます。

サンプルコード(ボタンとイベント処理)

ファイル作成

「Java54」フォルダに CounterApp.java という名前でファイルを作成します

コード入力

以下のコードを入力します。

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

public class CounterApp {
    private int count = 0;

    public CounterApp() {
        JFrame frame = new JFrame("カウンター");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(300, 200);
        frame.setLayout(new BorderLayout());

        // カウント表示ラベル
        JLabel label = new JLabel("0", JLabel.CENTER);
        label.setFont(new Font("SansSerif", Font.BOLD, 48));

        // ボタンパネル
        JPanel buttonPanel = new JPanel();
        JButton plusBtn  = new JButton("+1");
        JButton minusBtn = new JButton("-1");
        JButton resetBtn = new JButton("リセット");

        // イベントリスナー(ラムダ式で登録)
        plusBtn.addActionListener(e -> {
            count++;
            label.setText(String.valueOf(count));
        });

        minusBtn.addActionListener(e -> {
            count--;
            label.setText(String.valueOf(count));
        });

        resetBtn.addActionListener(e -> {
            count = 0;
            label.setText("0");
        });

        buttonPanel.add(minusBtn);
        buttonPanel.add(resetBtn);
        buttonPanel.add(plusBtn);

        frame.add(label, BorderLayout.CENTER);
        frame.add(buttonPanel, BorderLayout.SOUTH);

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

    public static void main(String[] args) {
        SwingUtilities.invokeLater(CounterApp::new);
    }
}

コンパイル

javac CounterApp.java

実行

java CounterApp

ウィンドウが開き、+1・-1・リセットボタンでカウントを操作できます。

サンプルコード(ToDoリストGUIアプリ)

これまでターミナルで作ってきたToDoリストをGUIアプリとして実装します。

ファイル作成

「Java54」フォルダに TodoGuiApp.java という名前でファイルを作成します

コード入力

以下のコードを入力します。

import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;

public class TodoGuiApp {
    private final DefaultListModel<String> listModel = new DefaultListModel<>();

    public TodoGuiApp() {
        JFrame frame = new JFrame("ToDoリスト");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(400, 500);
        frame.setLayout(new BorderLayout(5, 5));

        // タスク一覧
        JList<String> taskList = new JList<>(listModel);
        taskList.setFont(new Font("SansSerif", Font.PLAIN, 14));
        JScrollPane scrollPane = new JScrollPane(taskList);

        // 入力パネル
        JPanel inputPanel = new JPanel(new BorderLayout(5, 0));
        JTextField taskField = new JTextField();
        taskField.setFont(new Font("SansSerif", Font.PLAIN, 14));
        JButton addBtn = new JButton("追加");

        inputPanel.add(taskField, BorderLayout.CENTER);
        inputPanel.add(addBtn, BorderLayout.EAST);

        // ボタンパネル
        JPanel btnPanel = new JPanel(new FlowLayout());
        JButton deleteBtn   = new JButton("削除");
        JButton completeBtn = new JButton("完了");
        JButton clearBtn    = new JButton("全クリア");

        btnPanel.add(completeBtn);
        btnPanel.add(deleteBtn);
        btnPanel.add(clearBtn);

        // イベント: タスク追加
        Runnable addTask = () -> {
            String text = taskField.getText().trim();
            if (!text.isEmpty()) {
                listModel.addElement("☐ " + text);
                taskField.setText("");
                taskField.requestFocus();
            }
        };

        addBtn.addActionListener(e -> addTask.run());

        // Enterキーでも追加できる
        taskField.addKeyListener(new KeyAdapter() {
            @Override
            public void keyPressed(KeyEvent e) {
                if (e.getKeyCode() == KeyEvent.VK_ENTER) {
                    addTask.run();
                }
            }
        });

        // イベント: 完了にする
        completeBtn.addActionListener(e -> {
            int index = taskList.getSelectedIndex();
            if (index >= 0) {
                String item = listModel.get(index);
                if (item.startsWith("☐ ")) {
                    listModel.set(index, "☑ " + item.substring(2));
                }
            }
        });

        // イベント: 削除
        deleteBtn.addActionListener(e -> {
            int index = taskList.getSelectedIndex();
            if (index >= 0) {
                listModel.remove(index);
            }
        });

        // イベント: 全クリア
        clearBtn.addActionListener(e -> {
            int result = JOptionPane.showConfirmDialog(
                frame, "すべてのタスクを削除しますか?", "確認",
                JOptionPane.YES_NO_OPTION);
            if (result == JOptionPane.YES_OPTION) {
                listModel.clear();
            }
        });

        // レイアウト
        JPanel southPanel = new JPanel(new BorderLayout(0, 5));
        southPanel.add(inputPanel, BorderLayout.NORTH);
        southPanel.add(btnPanel, BorderLayout.SOUTH);
        southPanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));

        frame.add(scrollPane, BorderLayout.CENTER);
        frame.add(southPanel, BorderLayout.SOUTH);

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

    public static void main(String[] args) {
        SwingUtilities.invokeLater(TodoGuiApp::new);
    }
}

コンパイル

javac TodoGuiApp.java

実行

java TodoGuiApp

ウィンドウが開き、タスクの追加・完了・削除・全クリアが操作できるToDoリストアプリが起動します。

コードの解説

SwingUtilities.invokeLater() はGUIの作成・更新を「イベントディスパッチスレッド(EDT)」で実行するためのメソッドです。Swingはスレッドセーフではないため、GUIに関する操作はすべてEDT上で行う必要があります。

JFrame はウィンドウ本体です。setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE) で閉じるボタンを押したときにプログラムを終了するよう設定します。setLayout() でレイアウトマネージャーを指定し、コンポーネントの配置方法を決めます。BorderLayout は上下左右中央の5か所に配置できます。

addActionListener(e -> ...) でボタンのクリックイベントを登録します。ラムダ式を使うことで簡潔に書けます。これは以前学んだ関数型インターフェース(ActionListener)の活用です。

DefaultListModel<String> はJListに表示するデータを管理するモデルクラスです。listModel.addElement() でリストに要素を追加し、listModel.remove() で削除します。Swingはモデルとビューが分離された「MVC(Model-View-Controller)」パターンを採用しており、DefaultListModel がモデル、JList がビューに相当します。

JOptionPane.showConfirmDialog() はダイアログボックスを表示するメソッドです。確認ダイアログを1行で表示できます。

まとめ

Swingを使うことで、標準ライブラリだけでデスクトップアプリのGUIが作れます。JFrame でウィンドウを作り、JButton・JLabel・JTextField などのコンポーネントを配置し、addActionListener でイベントを登録するという基本の流れを覚えておきましょう。GUIはすべて SwingUtilities.invokeLater() で起動することも重要です。現在の現場ではJavaFXやWeb技術を使うことが多いですが、Swingの考え方(イベント駆動・MVC)はどのGUIフレームワークでも共通しているため、ここで学んだことは応用が効きます。

2026/08/14(金) ぱんまる

コメント

タイトルとURLをコピーしました