6日でできる 新Java入門|改良2:クイズゲームのためのSwing入門①

Swingを知れば、Javaのクイズゲームは「文字だけの画面」から「クリックして遊べるアプリ」へ進化する

前回までの改良では、クイズゲームの問題データをアニメクイズ用に差し替えました。
dragonball_quiz.txt、kimetsu_quiz.txt、jojo_quiz.txt を使うことで、ドラゴンボール・クイズ、鬼滅の刃・クイズ、ジョジョの奇妙な冒険・クイズを選べる形にしました。

ここまでのクイズゲームは、コマンドライン上で文字を入力して遊ぶ CUI アプリでした。
CUI は仕組みを学ぶには分かりやすいですが、ユーザーが直感的に操作するには少し物足りないところもあります。

そこで、ここからはクイズゲームを GUI 化していきます。

GUI とは、ボタン、ラベル、ウィンドウ、選択リストなどを使って、画面上で操作できる形式のことです。
たとえば、ジャンルをコンボボックスから選び、スタートボタンを押し、4つの選択肢ボタンをクリックして答えるような形です。

今回の記事では、いきなり完成版の GUI プログラムを掲載するのではなく、まず Swing の基本から確認します。
Swingとは何か、なぜ AWT ではなく Swing を使うのか、そしてクイズゲームの GUI 化で使う Swing の命令の前半部分を中心に解説していきます。

なお、完成版の QuizGame.java、QuizGenre.java、QuizManager.java は、最後の記事である「改良4:クイズゲームをGUIにする」でまとめて掲載します。
この記事では、Swing の部品や考え方を理解することを目的にします。

Swingとは

Swing は、Javaで GUI アプリケーションを作るためのライブラリです。
画面にウィンドウを表示したり、ボタンを置いたり、文字を表示したり、選択リストを作ったりできます。

Javaで GUI を作るとき、Swing を使うと次のような画面部品を扱えます。

Swingの部品役割
JFrameアプリのウィンドウを作る
JPanel部品をまとめるための領域を作る
JLabel文字を表示する
JButtonクリックできるボタンを作る
JComboBox選択リストを作る
JOptionPaneメッセージダイアログを表示する
Timer一定時間後に処理を実行する

クイズゲームを GUI 化する場合、これらの部品を組み合わせて画面を作ります。

たとえば、タイトル画面では、次のような部品が必要になります。

画面要素Swingで使う部品
アプリタイトルJLabel
ジャンル選択JComboBox
スタートボタンJButton
全体のウィンドウJFrame
部品を配置する領域JPanel

CUI版では、文字を表示して、キーボードから番号を入力していました。
GUI版では、画面に部品を配置し、ユーザーがクリックした操作に応じて処理を進めていきます。

Swingで作るGUIアプリのイメージ

Swingで作るクイズゲームは、次のような流れになります。

画面内容
タイトル画面アプリ名、ジャンル選択、スタートボタンを表示する
クイズ画面問題文と4つの選択肢ボタンを表示する
結果画面最終得点とタイトルへ戻るボタンを表示する

CUI版では、上から順に文字が流れていく形でした。
一方、GUI版では画面を切り替えながら進みます。

たとえば、スタートボタンを押すと、タイトル画面からクイズ画面へ切り替わります。
選択肢ボタンを押すと、正解・不正解が表示され、少し待って次の問題へ進みます。
全問が終わると、結果画面へ切り替わります。

このように、GUI化では「処理の順番」だけでなく、「画面の状態」を考える必要があります。

AWTではなくSwingを使う理由

Javaには、Swingより前から存在する AWT という GUI 用の仕組みもあります。
AWT は Abstract Window Toolkit の略で、Java初期からあるGUIライブラリです。

では、なぜ今回のクイズゲームでは AWT ではなく Swing を使うのでしょうか。

主な理由は、Swingのほうが学習用のGUIアプリを作りやすく、画面部品も扱いやすいからです。

比較項目AWTSwing
登場時期Java初期からあるAWTの後に登場
部品の種類基本的な部品が中心豊富な部品が使える
見た目OSに依存しやすいJava側で見た目を制御しやすい
軽量性OSの部品に依存する重い部品が多いJavaで描画する軽量部品が中心
学習用途基礎理解には使える実用的なGUI学習に向いている

AWTでもボタンやウィンドウは作れます。
ただし、Swingには JLabel、JButton、JPanel、JComboBox、JOptionPane など、学習用にも実用的にも使いやすい部品がそろっています。

今回のクイズゲームでは、タイトル画面、クイズ画面、結果画面を切り替えながら表示します。
さらに、ジャンル選択、選択肢ボタン、結果表示など、複数の画面部品を組み合わせます。

そのため、Swingを使うほうが自然です。

SwingとAWTの関係

SwingとAWTは完全に別物ではありません。
Swingの画面作成では、AWTのクラスも一緒に使います。

たとえば、GUI化したクイズゲームでは、次のような import が使われます。

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

ここで、javax.swing は Swing の部品を使うためのパッケージです。
一方、java.awt はレイアウト、色、フォント、サイズなどに関係する部品を使うために利用します。

import主な役割
javax.swing.*JFrame、JPanel、JLabel、JButton などを使う
java.awt.*BorderLayout、CardLayout、Color、Font などを使う
java.awt.event.*ボタンを押したときのイベント処理を使う

つまり、GUI画面の部品は Swing、配置や見た目の一部は AWT、クリック処理は event 系のクラス、という形で組み合わせます。

クイズゲームで使うSwingの前半部分

ここからは、GUI化したクイズゲームで使う Swing 関連の命令を見ていきます。
この記事では前半として、主に画面の土台作りと、タイトル画面で使う部品を中心に解説します。

今回扱う主な内容は次のとおりです。

分類扱う内容
ウィンドウ作成JFrame
画面の土台JPanel
画面切り替えCardLayout
文字表示JLabel
選択リストJComboBox
ボタンJButton
配置BorderLayout、BoxLayout
見た目Font、Color、Dimension、BorderFactory

完成版プログラムそのものはこの記事では掲載しませんが、どの部品がどんな役割を持つのかを先に理解しておくと、後の記事でプログラム全体を見たときにかなり読みやすくなります。

JFrame:アプリのウィンドウを作る

Swingアプリの基本になるのが JFrame です。
JFrame は、アプリケーションのウィンドウそのものを表します。

クイズゲームでいうと、タイトル画面、クイズ画面、結果画面はすべて1つのウィンドウの中に表示されます。
そのウィンドウの土台になるのが JFrame です。

JFrameで行うこと内容
タイトルを設定するウィンドウ上部に表示する名前を決める
閉じる動作を設定する×ボタンを押したときに終了するようにする
サイズを設定する画面の幅と高さを決める
表示位置を設定する画面中央に表示する
パネルを追加する中身の画面を配置する

代表的な設定は次のようなものです。

setTitle("アニメクイズゲーム");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(760, 520);
setLocationRelativeTo(null);

それぞれの意味を整理します。

命令内容
setTitleウィンドウのタイトルを設定する
setDefaultCloseOperation閉じるボタンを押したときの動作を設定する
setSizeウィンドウサイズを設定する
setLocationRelativeTo(null)ウィンドウを画面中央に表示する

CUI版では、コマンドプロンプトやターミナルに文字を表示していました。
GUI版では、まず JFrame でアプリ専用のウィンドウを作るところから始まります。

JPanel:部品を配置するための土台

JPanel は、ボタンやラベルなどの部品をまとめて置くための領域です。
JFrame が家全体だとすると、JPanel は部屋のようなものです。

クイズゲームでは、次のようなパネルを作ります。

パネル役割
タイトル画面用パネルタイトル、ジャンル選択、スタートボタンを置く
クイズ画面用パネル問題文、選択肢ボタン、結果メッセージを置く
結果画面用パネル得点とタイトルへ戻るボタンを置く

JPanel を使うことで、画面ごとに部品を整理できます。

たとえば、タイトル画面にはタイトル画面用の JPanel、クイズ画面にはクイズ画面用の JPanel を作ります。
それらをあとで CardLayout で切り替えることで、1つのウィンドウの中で画面遷移を表現できます。

CardLayout:画面をカードのように切り替える

GUI版クイズゲームでは、タイトル画面、クイズ画面、結果画面を切り替えます。
この画面切り替えに使うのが CardLayout です。

CardLayout は、複数の画面をカードのように重ねておき、必要なカードだけを表示するレイアウトです。

画面名内容
TITLEタイトル画面
QUIZクイズ画面
RESULT結果画面

イメージとしては、3枚のカードを重ねておき、場面に応じて前面に出すカードを変える形です。

cardLayout = new CardLayout();
mainPanel = new JPanel(cardLayout);

このように、CardLayout を使う JPanel を用意します。
そこにタイトル画面、クイズ画面、結果画面を追加します。

mainPanel.add(createTitlePanel(), "TITLE");
mainPanel.add(createQuizPanel(), "QUIZ");
mainPanel.add(createResultPanel(), "RESULT");

そして、表示したい画面を次のように切り替えます。

cardLayout.show(mainPanel, "TITLE");
cardLayout.show(mainPanel, "QUIZ");
cardLayout.show(mainPanel, "RESULT");
命令表示される画面
cardLayout.show(mainPanel, "TITLE")タイトル画面
cardLayout.show(mainPanel, "QUIZ")クイズ画面
cardLayout.show(mainPanel, "RESULT")結果画面

クイズゲームのように、画面の状態が段階的に変わるアプリでは、CardLayout がとても使いやすいです。

JLabel:文字を表示する部品

JLabel は、画面上に文字を表示するための部品です。
クイズゲームでは、タイトル、説明文、問題文、結果メッセージ、スコア表示などに使います。

使用場所表示内容
タイトル画面アニメクイズゲーム
タイトル画面ジャンルを選んでスタートを押してください
クイズ画面クイズタイトル
クイズ画面問題文
クイズ画面正解・不正解メッセージ
結果画面最終スコア

JLabel は文字を表示するだけの部品なので、ユーザーがクリックして操作するものではありません。
ただし、フォントや配置を調整することで、画面の印象を大きく変えられます。

たとえば、タイトルは大きく太字にします。

JLabel titleLabel = new JLabel("アニメクイズゲーム", SwingConstants.CENTER);
titleLabel.setFont(new Font("Meiryo", Font.BOLD, 38));

ここで使われている SwingConstants.CENTER は、文字を中央揃えにする指定です。

命令内容
new JLabelラベルを作る
SwingConstants.CENTER中央揃えにする
setFont文字の種類、大きさ、太さを設定する

クイズゲームでは、問題文も JLabel で表示します。
問題文は長くなることがあるため、HTML形式を使って中央寄せ表示する工夫もできます。

JButton:クリックできるボタン

JButton は、ユーザーがクリックできるボタンです。
クイズゲームでは、スタートボタン、選択肢ボタン、タイトルへ戻るボタンなどに使います。

ボタン役割
スタートジャンルを決めてゲームを開始する
選択肢1~4回答として選ぶ
タイトルへ結果画面からタイトル画面へ戻る

ボタンは、ただ画面に置くだけでは意味がありません。
クリックされたときに何をするかを登録する必要があります。

そこで使うのが addActionListener です。

startButton.addActionListener(new ActionListener() {
    public void actionPerformed(ActionEvent e) {
        startGame();
    }
});

このコードは、スタートボタンが押されたら startGame() を実行する、という意味です。

要素内容
addActionListenerボタンが押されたときの処理を登録する
ActionListenerイベントを受け取るための仕組み
actionPerformed実際にボタンが押されたときに動くメソッド
startGame()ゲーム開始処理

CUI版では、ユーザーが番号を入力して Enter を押すことで処理が進みました。
GUI版では、ボタンをクリックすることで処理が進みます。

この「クリックされたら処理を実行する」という考え方が、GUIプログラミングの基本です。

JComboBox:選択リストを作る

JComboBox は、複数の候補から1つを選ぶための部品です。
今回のクイズゲームでは、ジャンル選択に使います。

CUI版では、次のように番号を入力してジャンルを選んでいました。

1: ドラゴンボール・クイズ
2: 鬼滅の刃・クイズ
3: ジョジョの奇妙な冒険・クイズ
==>

GUI版では、JComboBox を使ってリストから選べるようにします。

genreComboBox = new JComboBox<QuizGenre>(QuizGenre.values());

ここでは、QuizGenre.values() によって enum に定義されているジャンル一覧を取得し、それを JComboBox に入れています。

部分内容
JComboBoxQuizGenre 型の選択リスト
QuizGenre.values()enum の全ジャンルを取得
getSelectedItem()選択されたジャンルを取得

JComboBox に QuizGenre を入れる場合、画面に表示される文字は toString() の戻り値になります。
そのため、QuizGenre 側で toString() を定義しておくと、コンボボックスにタイトル名を表示できます。

public String toString() {
    return title;
}

これにより、DRAGONBALL という enum 名ではなく、ドラゴンボール・クイズ のような分かりやすい表示になります。

Font:文字の見た目を整える

Swingでは、setFont を使って文字の見た目を調整できます。
クイズゲームでは、タイトルや問題文、ボタンの文字を見やすくするために Font を使います。

new Font("Meiryo", Font.BOLD, 38)

この指定は、メイリオ、太字、38px相当の大きさという意味です。

要素内容
Meiryo日本語表示に向いたフォント
Font.BOLD太字
Font.PLAIN通常の太さ
数値文字サイズ

たとえば、タイトルは大きく太字にし、説明文は少し小さめの通常文字にします。

表示場所フォント設定の考え方
タイトル大きく太字
説明文読みやすい通常サイズ
問題文目立つように太字
ボタン押しやすく見えるサイズ

GUIでは、同じ文字でもサイズや太さで印象が変わります。
学習用アプリでは、重要な情報を大きく、補足的な情報を少し小さくすると読みやすくなります。

Color:背景色を設定する

Swingでは、setBackground を使って背景色を設定できます。
今回のクイズゲームでは、タイトル画面や結果画面に淡い青系の背景色を使っています。

panel.setBackground(new Color(235, 245, 255));

Color には RGB の値を指定します。
RGB は、赤、緑、青の強さを数値で表す方法です。

指定意味
new Color(235, 245, 255)淡い青系の色
Color.WHITE
setBackground背景色を設定する

白と青を基調にすると、学習教材らしく、すっきりした画面にしやすいです。

Dimension:部品の大きさを指定する

Dimension は、部品の幅と高さを指定するときに使います。
たとえば、スタートボタンやジャンル選択リストの大きさを調整できます。

startButton.setPreferredSize(new Dimension(180, 50));

これは、スタートボタンの希望サイズを 幅180、高さ50 にする指定です。

命令内容
new Dimension(180, 50)幅180、高さ50のサイズ情報
setPreferredSize部品の希望サイズを設定する

ただし、Swingではレイアウトマネージャが最終的な配置やサイズを調整します。
そのため、setPreferredSize は「このくらいの大きさにしたい」という希望を伝えるものだと考えると分かりやすいです。

BorderFactory:余白を作る

画面を見やすくするには、部品同士の間隔や余白が大切です。
Swingでは、BorderFactory.createEmptyBorder を使って余白を作れます。

titleLabel.setBorder(BorderFactory.createEmptyBorder(50, 10, 20, 10));

この指定は、上、左、下、右の余白を設定しています。

順番意味
50上の余白
10左の余白
20下の余白
10右の余白

余白がない画面は、部品が詰まって見えます。
逆に、適切な余白を入れると、タイトルやボタンが見やすくなり、操作しやすい画面になります。

BorderLayout:上下左右中央に配置する

BorderLayout は、画面を5つの領域に分けて部品を配置するレイアウトです。

領域位置
BorderLayout.NORTH
BorderLayout.SOUTH
BorderLayout.WEST
BorderLayout.EAST
BorderLayout.CENTER中央

タイトル画面では、上にタイトル、中央に説明文やジャンル選択、ボタンを置くような構成にできます。

JPanel panel = new JPanel(new BorderLayout());
panel.add(titleLabel, BorderLayout.NORTH);
panel.add(centerPanel, BorderLayout.CENTER);

このように書くと、titleLabel が上部、centerPanel が中央に配置されます。

BorderLayout は、大きな画面構成を作るときに便利です。
細かい部品の並びは別の JPanel に任せ、全体の配置を BorderLayout で整えると、画面が整理されます。

BoxLayout:縦方向に部品を並べる

BoxLayout は、部品を縦や横に並べるためのレイアウトです。
タイトル画面では、説明文、ジャンル選択、スタートボタンを縦に並べるために使えます。

centerPanel.setLayout(new BoxLayout(centerPanel, BoxLayout.Y_AXIS));

BoxLayout.Y_AXIS は、縦方向に並べる指定です。

指定内容
BoxLayout.Y_AXIS縦方向に並べる
BoxLayout.X_AXIS横方向に並べる

さらに、Box.createVerticalStrut を使うと、部品の間に縦方向の空白を入れられます。

centerPanel.add(Box.createVerticalStrut(25));

これにより、説明文とジャンル選択、ジャンル選択とスタートボタンの間に余白を作れます。

タイトル画面の部品構成

ここまで見てきた部品を組み合わせると、タイトル画面は次のような構造になります。

部品役割
JFrameアプリ全体のウィンドウ
mainPanel画面切り替え用の親パネル
titlePanelタイトル画面用のパネル
JLabelアプリタイトルや説明文を表示
JComboBoxジャンルを選ぶ
JButtonスタートする
BorderLayoutタイトルと中央エリアを配置
BoxLayout中央エリアの部品を縦に並べる

この構造を理解しておくと、後で完成版の QuizGame.java を読んだときに、画面がどのように作られているか分かりやすくなります。

CUI版とGUI版の違い

ここで、CUI版とGUI版の違いを整理しておきます。

項目CUI版GUI版
表示方法文字を順番に表示するウィンドウに部品を配置する
操作方法キーボードで番号入力ボタンや選択リストを操作
ジャンル選択数字を入力JComboBox から選ぶ
回答方法1~4 を入力選択肢ボタンをクリック
画面遷移文字の流れで進むCardLayout で画面を切り替える
エラー表示文字で表示JOptionPane などで表示できる

CUI版では、処理の順番がそのまま画面に出ます。
GUI版では、画面部品とイベント処理を組み合わせて、ユーザーの操作に反応する形になります。

この違いを理解することが、Swing学習の大きな入口です。

図:Swingで作るクイズゲーム画面の土台

↓クリックすると拡大表示されます。

この図が示していること

Swingアプリでは、JFrame を土台にして、その中に JPanel を置き、CardLayout によってタイトル画面、クイズ画面、結果画面を切り替える構造になっていることを示しています。

この図から分かること

GUIアプリは、1つのウィンドウの中に複数の画面を用意し、必要に応じて表示する画面を切り替えることで進行することが分かります。

図:タイトル画面で使うSwing部品

↓クリックすると拡大表示されます。

この図が示していること

タイトル画面が、JLabel、JComboBox、JButton などのSwing部品を組み合わせて作られていることを示しています。

この図から分かること

GUI画面は、ひとつの大きな命令で作るのではなく、小さな部品を組み合わせて構成することが分かります。また、Font や Color などを使って見た目を整えることも理解できます。

次の記事につながるポイント

今回の記事では、Swingとは何か、AWTではなくSwingを使う理由、そしてクイズゲームのGUI化で使うSwing部品の前半を見てきました。

ここで特に大切なのは、次の考え方です。

ポイント内容
JFrameアプリのウィンドウを作る
JPanel部品を置く領域を作る
CardLayoutタイトル、クイズ、結果画面を切り替える
JLabel文字を表示する
JButtonクリック操作を受け取る
JComboBoxジャンル選択を行う
レイアウト部品を見やすく配置する

次の記事「改良3:クイズゲームのためのSwing入門②」では、クイズゲームで使用したSwingの命令の後半部分を扱います。
具体的には、イベント処理、ActionListener、ActionEvent、Timer、JOptionPane、SwingUtilities.invokeLater など、ユーザー操作に反応して画面を動かすための仕組みを中心に解説していきます。