Java入門|GUIアプリケーションの基本

はじめてのGUIアプリ入門。キーボードだけの世界から、ウィンドウが動く新しいJavaの冒険へ。

これまでのJava学習では、画面に文字を表示したり、キーボードから値を受け取ったりしながら、順番に処理が進むプログラムを中心に学んできました。これは、たとえば悟空が修行メニューを上から順にこなしていくような流れです。
しかし、実際に私たちが日ごろ使っているアプリケーションは、それだけではありません。画面にウィンドウが現れ、ボタンを押したり、マウスで操作したり、閉じるボタンを押して終了したりします。こうした見た目のあるアプリケーションこそ、GUIアプリケーションです。

ドラゴンボールの世界でたとえるなら、これまで学んできたCUIのプログラムは、修行場で先生の指示を1つずつ聞いて動くスタイルです。それに対してGUIアプリケーションは、天下一武道会の受付画面や、カプセルコーポレーションの装置パネルのように、見た目の部品を通して人が直接操作できる仕組みです。
この仕組みをJavaで作れるようになると、プログラムは「命令を実行するだけのもの」から、「人が触って使うもの」へと大きく広がっていきます。

ここでは、JavaでGUIアプリケーションを作る第一歩として、まずはウィンドウを1つ表示する基本を、ドラゴンボールの世界観に置きかえながら、ていねいに見ていきます。

GUIアプリケーションとは何か

GUIは Graphical User Interface の略です。
日本語では、画面上の見た目を通して操作する仕組みと考えると分かりやすいです。

たとえば、次のようなものはGUIアプリケーションです。

できることGUIでの見え方
アプリを起動するウィンドウが開く
内容を確認する文字や画像が表示される
操作するボタンやメニューをクリックする
終了する閉じるボタンを押す

ドラゴンボールの世界でいえば、神様の神殿にある装置や、ブルマが作る分析マシンの操作パネルのようなものです。
画面に「見える部品」があり、その部品に対して人が働きかけることで処理が進みます。

これまで学んできたプログラムとの違い

これまで多く扱ってきたプログラムは、実行すると上から下へ順に処理が進みました。
たとえば、メッセージを表示して、値を読み取り、計算して、結果を表示して終了する、という流れです。

一方、GUIアプリケーションは少し考え方が変わります。

項目これまでのプログラムGUIアプリケーション
操作方法キーボード中心マウスやウィンドウ操作
画面文字中心見た目のあるウィンドウ
処理の進み方上から順番に進みやすいユーザー操作に応じて動く
終了のきっかけ処理が終わると終了閉じる操作などで終了

ドラゴンボール風にいえば、これまでのプログラムは「悟空に最初から最後まで決められた修行をさせる流れ」です。
GUIアプリケーションは「修行場の操作盤を見ながら、どのボタンを押すかで次の動きが変わる流れ」です。

この違いがあるため、GUIではウィンドウを作ることと、そのウィンドウで起こる出来事に反応することがとても大切になります。

AWTとは何か

JavaでGUIアプリケーションを作る方法はいくつかありますが、基本としてよく登場するのが AWT です。
AWT は Abstract Window Toolkit の略で、ウィンドウやボタンなどを扱うための機能をまとめたライブラリです。

今回は、このAWTを使って、まずは最も基本となるウィンドウの作成を見ていきます。

AWTで扱う代表的な役割を整理すると、次のようになります。

クラスや機能役割
Frameウィンドウ本体を表す
setSize()ウィンドウの大きさを決める
setVisible()ウィンドウを表示する
WindowAdapterウィンドウの出来事を受け取るための補助クラス
windowClosing()閉じる操作が行われたときの処理

ドラゴンボールの世界でたとえると、Frame は修行場のコントロールルームそのものです。
その部屋に大きさを与え、見えるようにして、さらに閉じる操作に反応できるように整えていくイメージです。

ウィンドウを表示する基本の考え方

GUIアプリケーションの最初の目標は、とてもシンプルです。
画面にウィンドウを1つ表示することです。

これを実現するためには、次の流れで考えると分かりやすいです。

手順内容
1Frame をもとにしたクラスを作る
2そのクラスのオブジェクトを作る
3タイトルを決める
4サイズを決める
5画面に表示する
6閉じる操作に反応できるようにする

これは、ブルマが新しい修行モニターを作る流れに似ています。
まず装置の土台を作り、名前を付けて、大きさを決めて、実際に起動する。そして最後に、停止ボタンを押したらきちんと終了するようにしておくわけです。

サンプルプログラム

ファイル名:Sample1.java

import java.awt.*;
import java.awt.event.*;

public class Sample1 extends Frame
{
    public static void main(String[] args)
    {
        Sample1 sm = new Sample1();
    }

    public Sample1()
    {
        super("修行スケジュール");
        addWindowListener(new SampleWindowListener());

        setSize(320, 200);
        setVisible(true);
    }

    class SampleWindowListener extends WindowAdapter
    {
        public void windowClosing(WindowEvent e)
        {
            System.exit(0);
        }
    }

    public void paint(Graphics g)
    {
        g.drawString("きょうの修行を開始します", 70, 100);
    }
}

実行結果

このプログラムでできること

このプログラムを実行すると、タイトルが「修行スケジュール」のウィンドウが表示され、その中に「きょうの修行を開始します」という日本語のメッセージが描かれます。
さらに、右上の閉じるボタンを押すと、アプリケーションが終了します。

とても小さなプログラムですが、GUIアプリケーションとして大切な要素がしっかり入っています。
つまり、

  • ウィンドウを作る
  • タイトルを付ける
  • サイズを決める
  • 表示する
  • ウィンドウに文字を書く
  • 閉じる操作に対応する

という基本が、ひと通りそろっています。

プログラムの全体像をやさしく整理する

このプログラムは一見すると少し長く見えますが、役割ごとに分けて考えると理解しやすいです。

部分役割
import 文AWTやイベント処理の機能を使えるようにする
class Sample1 extends Frameウィンドウとしてふるまうクラスを作る
main()GUIアプリを起動する入口
コンストラクタタイトル、サイズ、表示などの初期設定をする
SampleWindowListener閉じる操作に対応する
paint()ウィンドウの中に文字を描く

ドラゴンボール風にまとめると、Sample1 は「修行場モニター」の設計図をもとに作られた実体です。
main() でその装置を起動し、コンストラクタで見た目を整え、paint() で表示内容を書き込み、WindowListener で終了操作に対応しています。

Frameを拡張する意味

このプログラムでは、Sample1 クラスが Frame を拡張しています。

public class Sample1 extends Frame

ここでのポイントは、Frameの機能を受け継いだ新しいクラスを作っていることです。
Frame はウィンドウそのものを表すクラスなので、それを拡張すると、Sample1 もウィンドウとして動けるようになります。

これはドラゴンボールでいえば、「修行場の基本装置」をもとにして、自分専用の修行モニターを作るようなものです。
元となる機能を引き継ぎながら、自分に必要な動きや見た目を加えられます。

main()メソッドで何をしているか

main()メソッドでは、次の1行が実行されています。

Sample1 sm = new Sample1();

これによって Sample1 のオブジェクトが作られます。
オブジェクトが作られると、コンストラクタが呼び出され、ウィンドウの設定がまとめて行われます。

つまり、main() は「アプリを起動する合図」を出している場所です。
悟空が修行場のスイッチを押して装置を立ち上げる場面をイメージすると分かりやすいです。

コンストラクタで行っている設定

コンストラクタの中では、ウィンドウに必要な初期設定を行っています。

public Sample1()
{
    super("修行スケジュール");
    addWindowListener(new SampleWindowListener());

    setSize(320, 200);
    setVisible(true);
}

それぞれの役割を見てみましょう。

記述役割
super("修行スケジュール")ウィンドウのタイトルを設定する
addWindowListener(...)閉じる操作を受け取れるようにする
setSize(320, 200)幅320、高さ200にする
setVisible(true)ウィンドウを画面に表示する

この部分は、修行場の装置を使える状態に整える準備です。
名前札を付けて、サイズを決めて、操作受付を有効にして、最後に電源を入れるような流れです。

super()でタイトルを決める

super("修行スケジュール") は、親クラスである Frame のコンストラクタを呼び出しています。
ここで指定した文字列が、そのままウィンドウのタイトルバーに表示されます。

たとえば、ここを別の文字に変えれば、ウィンドウ上部のタイトルも変わります。

例:

super("カプセルコーポ修行管理");

このように、タイトルはウィンドウの役割を伝える看板のようなものです。
ユーザーが見たときに、どんな画面なのかがすぐ伝わる名前にすると分かりやすくなります。

setSize()で大きさを決める

setSize(320, 200);

これはウィンドウの大きさを設定する命令です。
320 は横幅、200 は縦幅です。

もし文字が多いのにウィンドウが小さすぎると、内容が見にくくなることがあります。
逆に、大きすぎると空白が多く感じられることもあります。
GUIでは、見た目の使いやすさも大切なので、サイズの設定には意味があります。

ドラゴンボール風にいえば、これは修行部屋の広さを決めることです。
狭すぎると悟空もベジータも動きにくいですし、広すぎると今度は持て余してしまいます。

setVisible(true)で表示する

setVisible(true);

これがないと、設定したウィンドウは画面に現れません。
部屋の準備が終わっていても、表に出していなければ見えないのと同じです。

GUIを初めて学ぶときは、この命令の存在を見落としやすいです。
「ちゃんと書いたのに表示されない」と感じたときは、この部分を確認するとよいです。

paint()で文字を描く

今回のサンプルでは、ウィンドウの中にメッセージを表示するために paint() メソッドを使っています。

public void paint(Graphics g)
{
    g.drawString("きょうの修行を開始します", 70, 100);
}

paint() は、ウィンドウの中に絵や文字を描くためのメソッドです。
Graphics 型の g を使って、実際に描画を行います。

今回使っている drawString() の意味は次の通りです。

記述意味
"きょうの修行を開始します"表示する文字列
70横方向の位置
100縦方向の位置

この部分は、修行場のモニターに「本日の案内文」を書き込んでいるようなものです。
GUIでは、ただウィンドウを出すだけでなく、その中に何を見せるかもとても重要です。

paint() が呼ばれるタイミング

public void paint(Graphics g) は「自分で呼ぶものではなく、AWT(OSやJavaの描画システム)によって自動的に呼ばれるメソッド」です。

代表的なタイミングを整理するとこうなります。

タイミング説明
① ウィンドウが表示されたときsetVisible(true) を呼んだ直後
② ウィンドウが再描画されたとき最小化→復元、他のウィンドウに隠れていた部分が表示されたとき
③ サイズ変更されたときsetSize やユーザーのリサイズ
④ repaint() を呼んだとき明示的に再描画を要求した場合

コードでの流れ

このプログラムでは、次の流れで paint() が呼ばれます。

Sample1 sm = new Sample1();

setVisible(true);

➡このタイミングで 画面表示が必要になるため paint() が呼ばれる

public void paint(Graphics g)

➡「きょうの修行を開始します」が描画される

ポイント(超重要)

paint() はこういう性質があります。

ポイント内容
自分で直接呼ばないpaint() を直接呼ぶのはNG
再描画は repaint() を使うrepaint() → 内部で paint() が呼ばれる
何度も呼ばれる可能性がある状況によって何回も実行される

ウィンドウを閉じられるようにする理由

GUIアプリケーションでは、ウィンドウを表示するだけでは不十分です。
ユーザーが右上の閉じるボタンを押したときに、きちんと終了できる必要があります。

そのために使っているのが、次の部分です。

addWindowListener(new SampleWindowListener());

そして、実際の処理は内部クラスで定義されています。

class SampleWindowListener extends WindowAdapter
{
    public void windowClosing(WindowEvent e)
    {
        System.exit(0);
    }
}

ここでの流れを整理すると、次のようになります。

流れ内容
1ウィンドウで出来事が起こる
2閉じる操作が行われる
3windowClosing() が呼ばれる
4System.exit(0) でプログラムを終了する

これは、修行場の停止ボタンに反応して、装置を安全に終了する仕組みと考えると分かりやすいです。

WindowAdapterを使う理由

WindowAdapter は、ウィンドウ関連のイベント処理を簡単に書くための補助クラスです。
ウィンドウには、開いた、閉じた、最小化した、アクティブになった、などいろいろな出来事があります。
そのすべてに対応するのは大変なので、必要なものだけを選んで書きやすくするために WindowAdapter が使われます。

今回は、閉じる操作だけに注目したいので、windowClosing() だけを用意しています。

この書き方のよいところは、今必要な処理だけに集中できることです。
はじめてGUIを学ぶ段階では、とても扱いやすい方法です。

GUIの考え方はイベント処理と深く結びつく

GUIアプリケーションでは、ユーザーがいつ何をするか分かりません。
ボタンを押すかもしれませんし、ウィンドウを閉じるかもしれません。
だからこそ、GUIではイベントが起きたときにどう動くかを決めておく必要があります。

今回のサンプルでいえば、イベントは「ウィンドウを閉じる操作」です。
その出来事が起きたら、windowClosing() が呼ばれ、プログラムが終了します。

今後GUIを学んでいくと、

  • ボタンを押したら何をするか
  • マウスを動かしたらどうするか
  • キーを押したらどう反応するか

といった広がりが見えてきます。
その入口として、今回のウィンドウを閉じる処理はとても大事な基本です。

この図が示していること

この図では、プログラムの起動からウィンドウ表示、さらに閉じる処理までの流れがひと目で分かります。
main() が出発点になり、Sample1 のオブジェクトが作られ、Frame の機能を使ってウィンドウが表示されます。
さらに、閉じる操作が行われたときに windowClosing() が呼ばれ、アプリケーションが終了する関係も確認できます。
つまり、GUIアプリの最小構成がどのようにつながっているかを視覚的に理解できる図になります。

このサンプルから理解しておきたいこと

このプログラムで特に大切なのは、次の4点です。

大切な点内容
ウィンドウは Frame をもとに作るGUIの土台になる
コンストラクタで初期設定を行うタイトル、サイズ、表示をまとめて準備する
paint() で画面に文字を描けるウィンドウ内の見た目を作れる
イベント処理で閉じる操作に対応するGUIらしい動きの基本になる

この4つを押さえるだけでも、GUIアプリケーションの入り口がかなり見えやすくなります。

はじめてGUIを学ぶときに戸惑いやすい点

GUIは見た目がある分、CUIのプログラムよりも少し複雑に感じやすいです。
特に、次の点で戸惑うことがあります。

戸惑いやすい点理由
extends Frame の意味ウィンドウの機能を引き継ぐ考え方に慣れていない
コンストラクタで設定する流れmain() との役割分担が最初は見えにくい
paint() の存在文字表示が println() ではなく描画になる
イベント処理ユーザー操作に応じて動く考え方が新しい

でも、全部を一気に難しく考えなくて大丈夫です。
まずは「ウィンドウを出す」「中に文字を見せる」「閉じたら終わる」という3つの流れがつかめれば十分です。
これは、天下一武道会に出る前に、まず道着を着て会場に入るところから始めるようなものです。最初から大技を全部覚える必要はありません。

GUIアプリケーションの第一歩としての意味

今回学ぶ内容は、派手な画面を作る段階ではありません。
ですが、とても大事な土台です。

なぜなら、どんなGUIアプリケーションでも、最初は

  • ウィンドウがある
  • その中に何かを表示する
  • ユーザーの操作に反応する

という基本の組み合わせでできているからです。

ドラゴンボールでいえば、どれだけ強い戦士でも、最初は構えや気のコントロールから始まります。
GUIも同じで、今回の基本をしっかり理解しておくと、この先ボタンやテキストフィールド、入力処理などを学ぶときにぐっと分かりやすくなります。

今の段階で意識しておくとよい見方

この段階では、コードを丸暗記する必要はありません。
それよりも、次の見方を身につけることが大切です。

  • どこがウィンドウ本体を作っているのか
  • どこでタイトルやサイズを決めているのか
  • どこで表示しているのか
  • どこで閉じる操作に反応しているのか
  • どこで画面の内容を描いているのか

このように役割で見られるようになると、GUIのコードがずっと読みやすくなります。

必要であれば、次に続けてこの内容をもとにしたより読みやすい学習記事形式へ整えて、さらに図を増やした版として書き直せます。