[第2回] Javaでクリニック向け予約・問診アプリを一から作ってみる 〜フォーム作成編〜 

# ✅ はじめに
こんにちは！前回の記事（[第1回] Javaでクリニック向け予約・問診アプリを一から作ってみる）では、作りたいアプリの概要や背景についてまとめました。
今回はその続きとして、
🎯 実際の予約フォームの作成
🎯 予約データのDB（SQLite）への保存
までを進めたので、その過程を備忘録としてまとめていきます！

「JaveでGUIってどう作るん？」
「DBとつなぐって何が必要？」
みたいな初歩的なところを学びながら簡易予約フォームを作ったので、同じような方の参考になれば嬉しいです🙌

# 💡 今回やったこと
✅ Java Swingでの予約フォーム作成
✅ SQLiteを使ったデータベース接続とデータ保存
→第３回（）
✅ 管理者画面（予約一覧の表示）の作成
→第４回（）

## 🖥️ 1. Javaでの予約フォーム作成
まずは予約データを入力するための画面をJava Swingで作成しました！
作ったフォームはこんな感じ👇

![予約用フォーム.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/867423/fb25a471-5118-45d8-8608-9e0b73f53320.png)

## ⚙ Swingの基本パーツ紹介
| コンポーネント | クラス名          | 役割                          | サンプルコード                                              |
| :------ | :------------ | :-------------------------- | :--------------------------------------------------- |
| ラベル     | `JLabel`      | 文字を表示（入力欄の見出しに使う）           | `JLabel nameLabel = new JLabel("名前:");`              |
| テキスト入力  | `JTextField`  | 1行のテキスト入力欄                  | `JTextField nameField = new JTextField(20);`         |
| 複数行入力   | `JTextArea`   | 複数行のテキスト入力欄（例: 症状入力）        | `JTextArea symptomArea = new JTextArea(3, 20);`      |
| スクロール   | `JScrollPane` | スクロールできる領域を作る（JTextAreaを包む） | `JScrollPane scroll = new JScrollPane(symptomArea);` |
| ボタン     | `JButton`     | クリックで処理を実行するボタン             | `JButton submitButton = new JButton("登録");`          |

## 🗂️ GridBagLayoutの基礎
各パーツの配置はGridBagLayoutを使って配置しました。
GridBagLayoutは、格子状（グリッド）にコンポーネントを配置するレイアウトマネージャーで、単純なグリッドレイアウト（GridLayout）とは違い、セルのサイズやコンポーネントの配置、余白、伸縮性など細かく調整可能な見栄え調整機能です。
詳しくは以下のリンクから確認できます！
https://www.tohoho-web.com/java/swing.htm#LookAndFeel

Java Swingで複雑なフォームやウィンドウを作るときの定番👇

| プロパティ                 | 意味            | 例                                           |
| :-------------------- | :------------ | :------------------------------------------ |
| `gridx` / `gridy`     | 配置位置（列・行）     | `gbc.gridx = 0; gbc.gridy = 1;`             |
| `fill`                | コンポーネントの伸縮設定  | `gbc.fill = GridBagConstraints.HORIZONTAL;` |
| `anchor`              | 位置揃え（東西南北・中央） | `gbc.anchor = GridBagConstraints.EAST;`     |
| `insets`              | 余白（上下左右）      | `gbc.insets = new Insets(5,5,5,5);`         |
| `weightx` / `weighty` | 余白の比率（伸びやすさ）  | `gbc.weightx = 1.0;`                        |


## 実装コード
コンポーネント配置のコードがもっとキレイに書けるんじゃないかな～と思いつつ、むりやり綺麗に配置しました。ここは反省点です(-_-;)
```java
// フレーム作成
        JFrame frame = new JFrame("予約フォーム");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(400,300);

        // パネル作成
        JPanel panel = new JPanel();
        frame.add(panel);
        GridBagLayout gbl = new GridBagLayout();
        panel.setLayout(gbl);
        GridBagConstraints gbc = new GridBagConstraints();
        gbc.fill = GridBagConstraints.HORIZONTAL;
        gbc.anchor = GridBagConstraints.WEST;

        // コンポーネント追加
        JLabel nameLabel = new JLabel("名前:");
        nameField = new JTextField(50);
        gbc.gridx=0;gbc.gridy=0;
        panel.add(nameLabel,gbc);
        gbc.gridx=1;gbc.gridy=0;gbc.gridwidth = 2;
        panel.add(nameField,gbc);

        maleButton = new JRadioButton("男性");
        femaleButton = new JRadioButton("女性");
        ButtonGroup genderGroup = new ButtonGroup();
        genderGroup.add(maleButton);
        genderGroup.add(femaleButton);
        gbc.gridx=3;gbc.gridy=0;gbc.gridwidth = 1;
        panel.add(maleButton,gbc);
        gbc.gridx=4;gbc.gridy=0;
        panel.add(femaleButton,gbc);

        gbc.gridx=0;gbc.gridy=2;
        panel.add(new JLabel("診療科目:"),gbc);
        cb = new JComboBox<>();
        cb.addItem("内科");
        cb.addItem("小児科");
        cb.addItem("皮膚科");
        gbc.gridx=1;gbc.gridy=2;
        panel.add(cb,gbc);

        gbc.gridx=0;gbc.gridy=3;
        panel.add(new JLabel("症状?:"),gbc);
        syusoField = new JTextArea(4,15);
        gbc.gridx=0;gbc.gridy=4;gbc.gridwidth = 3;
        panel.add(syusoField,gbc);

        ArrayList<String> years = new ArrayList<>();
        ArrayList<String> months = new ArrayList<>();
        ArrayList<String> days = new ArrayList<>();
        for (int i = 2025; i < 2030; i++) years.add(String.valueOf(i));
        for (int i = 1; i <= 12; i++) months.add(String.valueOf(i));
        for (int i = 1; i <= 31; i++) days.add(String.valueOf(i));

        yearBox = new JComboBox<>(new Vector<>(years));
        monthBox = new JComboBox<>(new Vector<>(months));
        dayBox = new JComboBox<>(new Vector<>(days));

        gbc.gridx=0;gbc.gridy=6;gbc.gridwidth = 1;
        panel.add(new JLabel("予約日:"),gbc);
        gbc.gridx=1;gbc.gridy=5;
        panel.add(new JLabel("年"),gbc);
        gbc.gridx=1;gbc.gridy=6;
        panel.add(yearBox,gbc);
        gbc.gridx=2;gbc.gridy=5;
        panel.add(new JLabel("月"),gbc);
        gbc.gridx=2;gbc.gridy=6;
        panel.add(monthBox,gbc);
        gbc.gridx=3;gbc.gridy=5;
        panel.add(new JLabel("日"),gbc);
        gbc.gridx=3;gbc.gridy=6;
        panel.add(dayBox,gbc);

        JButton submitButton = new JButton("送信");
        submitButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                saveReservation();  // データベース保存処理を呼ぶ
            }
        });
        gbc.gridx=2;gbc.gridy=7;
        panel.add(submitButton, gbc);

        frame.setVisible(true);
```

# 振り返り
・GridBagLayoutは細かい調整が可能
・gridx, gridy で位置を決めて、fillやweightxで伸縮を設定
・insetsやanchorで見た目の微調整ができる
・次回はUI的にも見栄えが良い手法を探してUIにもこだわりたい！