【JavaSwing】CardLayoutによる画面遷移

# ボタンで画面を切り替えられるGUIが作りたい！！
2020年7月現在JavaSwingを使って開発中のソフトに、Webサイトのようにボタンを押すと画面遷移する（画面が切り替わる）機能をつけたくて探していたところ、CardLayoutという機能を使うことで画面遷移が可能になるようなのでまとめておきたいと思います。

### 環境
- OS:Ubuntu18.04LTS
- JDK:OpenJDK 11.0.4

---
## JFrameを定義する
まず基本となるJFrameを定義します。

```java:PanelChangeTest.java
import javax.swing.*;

public class PanelChangeTest extends JFrame{

    public static void main(String[] args) {
        PanelChangeTest frame = new PanelChangeTest();
        frame.setTitle("画面遷移テスト");
        frame.setSize(900, 600);
        frame.setLocationRelativeTo(null);
        frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
        frame.setVisible(true);
    }
}
```

実行してみます。

```shell
javac PanelChangeTest.java && java PanelChange
```

![PanelChangeTest001.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150278/3178bb68-7cd9-4bec-2b8f-b886327afa0e.png)

無事実行できました。

---
## パネルと画面遷移用のボタンを追加する
次にパネルを追加します。手順は次の通り

- 画面遷移を目的とする3つのパネル(panel01, panel02, panel03)を定義します。
- 3つのパネルを格納する親パネル(cardPanel)を定義し、格納します。
- 画面遷移用のボタンを定義します。

```java:PanelChangeTest.java
import java.awt.*;
import javax.swing.*;

public class PanelChangeTest extends JFrame{

    JPanel cardPanel;
    CardLayout layout;

    public static void main(String[] args) {
        PanelChangeTest frame = new PanelChangeTest();
        frame.setTitle("画面遷移テスト");
        frame.setSize(900, 600);
        frame.setLocationRelativeTo(null);
        frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
        frame.setVisible(true);
    }

    public PanelChangeTest() {
        
        // panel01
        JPanel panel01 = new JPanel();
        JButton btn01 = new JButton("panel01");
        panel01.add(btn01);

        // panel02
        JPanel panel02 = new JPanel();
        panel02.setBackground(Color.DARK_GRAY);
        JButton btn02 = new JButton("panel02");
        panel02.add(btn02);

        // panel03
        JPanel panel03 = new JPanel();
        panel03.setBackground(Color.LIGHT_GRAY);
        JButton btn03 = new JButton("panel03");
        panel03.add(btn03);

        // CardLayout用パネル
        cardPanel = new JPanel();
        layout = new CardLayout();
        cardPanel.setLayout(layout);

        cardPanel.add(panel01, "panel01");
        cardPanel.add(panel02, "panel02");
        cardPanel.add(panel03, "panel03");

        // カード移動用ボタン
        JButton firstButton = new JButton("panel01");
        JButton secondButton = new JButton("panel02");
        JButton thirdButton = new JButton("panel03");

        JPanel btnPanel = new JPanel();
        btnPanel.add(firstButton);
        btnPanel.add(secondButton);
        btnPanel.add(thirdButton);

        // cardPanelとカード移動用ボタンをJFrameに配置
        Container contentPane = getContentPane();
        contentPane.add(cardPanel, BorderLayout.CENTER);
        contentPane.add(btnPanel, BorderLayout.PAGE_END);
    }
}
```
実行してみます。

```shell
javac PanelChangeTest.java && java PanelChange
```

![PanelChangeTest002.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150278/4e19b0b2-7c58-73ce-9eb6-baab1974e5e8.png)

追加したパネルとボタンが表示されました。
しかしこの段階では、画面下部のボタンを押しても画面遷移はできません。

---
## 画面遷移機能の実装
画面遷移の機能をつけて、画面下部のボタンを押すと画面が切り替わるようにします。

- ボタンクリック時の挙動を制御するためにクラス名に `implements ActionListener`を記述します。
- 3つのボタンそれぞれに`.addActionListener(this);`と`.setActionCommand("パネル名");`を記述して、ボタンに機能を付与します。
- `actionPerformed()`メソッドでそれぞれのボタンに対応した画面に切り替えられるように定義します。

```java:PanelChangeTest.java
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;

public class PanelChangeTest extends JFrame implements ActionListener{

    JPanel cardPanel;
    CardLayout layout;

    public static void main(String[] args) {
        PanelChangeTest frame = new PanelChangeTest();
        frame.setTitle("画面遷移テスト");
        frame.setSize(900, 600);
        frame.setLocationRelativeTo(null);
        frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
        frame.setVisible(true);
    }

    public PanelChangeTest() {
        
        // panel01
        JPanel panel01 = new JPanel();
        JButton btn01 = new JButton("panel01");
        panel01.add(btn01);

        // panel02
        JPanel panel02 = new JPanel();
        panel02.setBackground(Color.DARK_GRAY);
        JButton btn02 = new JButton("panel02");
        panel02.add(btn02);

        // panel03
        JPanel panel03 = new JPanel();
        panel03.setBackground(Color.LIGHT_GRAY);
        JButton btn03 = new JButton("panel03");
        panel03.add(btn03);

        // CardLayout用パネル
        cardPanel = new JPanel();
        layout = new CardLayout();
        cardPanel.setLayout(layout);

        cardPanel.add(panel01, "panel01");
        cardPanel.add(panel02, "panel02");
        cardPanel.add(panel03, "panel03");

        // カード移動用ボタン
        JButton firstButton = new JButton("panel01");
        firstButton.addActionListener(this);
        firstButton.setActionCommand("panel01");

        JButton secondButton = new JButton("panel02");
        secondButton.addActionListener(this);
        secondButton.setActionCommand("panel02");

        JButton thirdButton = new JButton("panel03");
        thirdButton.addActionListener(this);
        thirdButton.setActionCommand("panel03");

        JPanel btnPanel = new JPanel();
        btnPanel.add(firstButton);
        btnPanel.add(secondButton);
        btnPanel.add(thirdButton);
     
        // cardPanelとカード移動用ボタンをJFrameに配置
        Container contentPane = getContentPane();
        contentPane.add(cardPanel, BorderLayout.CENTER);
        contentPane.add(btnPanel, BorderLayout.PAGE_END);
    }

    public void actionPerformed(ActionEvent e) {
        String cmd = e.getActionCommand();

        layout.show(cardPanel, cmd);
    }
}
```
実行してみます。

```shell
javac PanelChangeTest.java && java PanelChange
```

![PanelChangeTest003.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150278/213c7609-58a5-8c68-d418-83f79df29843.png)

先程と同じ画面が表示されました。
画面下部のボタン「panel02」をクリックしてみます。

![PanelChangeTest004.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150278/387c3a26-9469-10f1-9c15-fb2cdfe9bc18.png)

panel02に切り替わりました。
同じく「panel03」をクリックしてみます。

![PanelChangeTest005.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150278/0ef2b47b-2605-df0c-4b16-21c9693af7dc.png)

panel03に切り替わりました。
尚、画面上部のボタンはパネル名を表示させるための便宜上のものなので今回のコードではボタンとしての機能はつけていません。

---
## まとめ
今回は、JavaSwingでGUIの画面遷移をテストしてみました。

あくまでテストだったので1つのファイルに3つのメソッドとシンプルなものとなりました。
実用的にするためには、

- 表示用のパネルをそれぞれ別クラスにする。
- 画面遷移用のボタンをメソッド化する

などして、可読性を保ちつつ、カスタマイズ性の高いクラス・メソッドの構成が必要だと感じました。

---
### 参考サイト
[Let'sプログラミング:Swingを使ってみよう](https://www.javadrive.jp/tutorial/)