学生向けプログラミング入門 | 無料

学生向けにプログラミングを無料で解説。Java、C++、Ruby、PHP、データベース、Ruby on Rails, Python, Django

Javaプログラミング入門その32 メニューを付加したプログラム

>>この記事には書き直した新しいページがあります。<<


<<前  [TOP]  次>>


GUIのプログラムを作成する場合に、最も基本となるのが、メニューを利用したプログラムです。
今回はメニューの基本として、MenuBar、MenuItem、Menuを使用します。
下記にクラスの関係をあげておきます。

Java.lang.Object
    +--java.awt.MenuComponent
        |
        +--java.awt.MenuBar
        +--java.awt.MenuItem
            |
            +--java.awt.CheckBoxMenuItem
            +--java.awt.Menu
                |
                +--java.awt.PopMenu



メニューはメニューアイテムによって構成され、メニューバーに配置します。
生成されたメニューバーはフレームに配置します。
Menu、MenuItem、CheckBoxMenuItem、でMenuを構成して、(複数の)MenuをMenuBarへ配置します。
MenuBarをFrameへ登録するとフレームの上部に配置されます。


MenuBarは各種メニューを配置するメニューバーで、フレームに設定されます。
メニューバーの表示位置を指定する必要はありません。
FrameのsetMenuBar()を利用してフレームに配置します。

Frame frame = new Frame("テストフレーム");
MenuBar menuBar = new MenuBar();
frame.setMenuBar(menuBar);



Menuは各種メニューアイテムを保持するポップアップウィンドウです。
MenuItemで構成されます。
Menuは、MenuItemのサブクラスなので、MenuItemの機能を持っています。
メニューの中にさらに別のメニューを入れることも可能です。
MenuをMenuBarへaddした場合、順に左から登録されます。
このとき、MenuBar.setHelpMenu(Menu)を使用すれば「ヘルプ」を表すメニューにすることも出来ます。
Menu.addSeparator()を用いることで、「区切り線」を入れることも可能です。

MenuBar menuBar = new MenuBar();
Menu menu1 = new Menu("メニュー1");
Menu menu2 = new Menu("メニュー2");
Menu menu3 = new Menu("ヘルプ");

//メニューをメニューバーに登録。左から順に並ぶ
menuBar.add(menu1);
menuBar.add(menu2);

//ヘルプメニューとして登録。
//実行されるシステムにより適当な位置に配置される
menuBar.setHelpMenu(menu3);



MenuItemは各種メニューアイテムの基本となる選択項目です。
生成したメニューアイテムは、Menuに配置します。
生成時にメニューアイテムの表示文字列を指定できます。

Menu menu = new Menu("メニュー");
MenuItem item1 = new MenuItem("アイテム1");
MenuItem item2 = new MenuItem("アイテム2");

//menuにメニューアイテムを登録。
//上から順に並ぶ。
//区切り線が入っている。
menu.add(item1);
menu.addSeparator();
menu.add(item2);



各種メニューアイテムでイベント処理を行う場合、java.awt.event.ActionListener[actionPerformed(ActionEvent)]を使用します。
通知されたイベント情報から、選択されたメニューアイテムを取得するにはいくつかの方法があります。
今回は2つ紹介します。


1.選択されたメニューアイテムを取得する。

/**コンストラクタ*/
public test() {

    MenuItem item1 = new MenuItem("アイテム1");
    MenuItem item2 = new MenuItem("アイテム2");

    item1.addActionListener(this);
    item2.addActionListener(this);
        ・
        ・
}

 /**メニューのイベントを処理*/
public void actionPerformed(ActionEvent evt) {

    //イベント情報から通知されたオブジェクトを取得
     Object obj = evt.getSource();

    //オブジェクトで分岐
     if(obj.equals(item1)) {
        //処理1
    }
    else if(obj.equals(item2)) {
        //処理2
     }
}



2.設定されているActionCommandを利用する(特に指定されていないときはメニューアイテムのラベルがActionCommandになる)。

/**コンストラクタ*/
public test() {

    MenuItem item1 = new MenuItem("アイテム1");
    MenuItem item2 = new MenuItem("アイテム2");

    item1.addActionListener(this);
    item2.addActionListener(this);
        ・
        ・
}

 /**メニューのイベントを処理*/
public void actionPerformed(ActionEvent evt) {

    //イベント情報から通知されたオブジェクトActionCommandを取得
     String str = evt.getActionCommand();

    //ActionCommandで分岐
     if(str.equals("アイテム1")) {
        //処理1
    }
    else if(str.equals("アイテム2")) {
        //処理2
     }
}



クラスメンバ(変数)へのアクセスを制御するには以下のような修飾子キーワードを使用します。

publicどのクラスからもアクセス可能
Protected同じパッケージ内のクラスと、このクラスを継承したクラスからアクセス可能
privateそのクラスからのみアクセス可能
指定なし同じパッケージ内のクラスからアクセス可能


Javaのプログラムでは、メソッドを使用しようとして期待しない動作が起こりえる場合にエラーを発生します。
このようなエラーを例外(Exception)といいます。
例外はjava.lang.Object-java.lang.throwableを元にしたクラス断層の構造となっています。

Java.lang.Object
    |
    +--java.lang.Throwable
        |
        +--java.lang.Error(プログラムがキャッチすべきでない重要な問題)
         +--java.lang.Exception(通常プログラムでキャッチされる可能性のある例外)
             |
            +--java.lang.RuntimeException(JVMでスローする例外のスーパークラス)



例外は、JVMかthrowキーワードによりスロー(throw)されます。
例外を処理するためにはtry-catch構造を用います。

/**
 *例外処理のテストを行う
*/
import java.io.FileReader;

 public class ExceptionTest1 {

    /**main()*/
    public static void main(String[] args) {
        //第一引数のファイルをnewする
        try {
            new FileReader(args[0]);
        }
        cath(Exception ex) {
            ex.printStackTrace();
        }
        finaly {
            System.out.println("終了");
        }
    }
}

finallyは例外があってもなくても実行されるもので省略可能です。
下記はAPIでのFileReaderの解説です。
何を例外とすればよいか確認してください。

FileReader

public FileReader(String fileName) throw FileNotFoundException

読み込み元のファイルの名前を指定して、新規FileReaderを作成します。

パラメータ:
FileName--読み込み元のファイルの名前

 例外:
FileNotFoundException--指定されたファイルが見つからない場合



throwを用いることでメソッドの呼び出し元へその例外をスローすることが出来ます。
このようにすることでメソッドを利用する側で柔軟な例外対応を行うことが出来ます。

/**
 *throwを行う
*/

import java.io.*;

 public class ExceptionTest2 {

    public void fileReader(String fileName) throw FileNotFoundException {
        new FileReader(fileName);
    }

    /** main() */
    public static void main(String[] args) {
        ExceptionTest2 test = new ExceptionTest2();

        try {
            test.fileReader(arg[0]);
        }
        catch (FileNotFoundException ex) {
            ex.printStackTrace();
        }
    }
}



以下のサンプルプログラムを作成して下さい。


【JumpGame2.java】

/**
*JumpGameを拡張して、メニューから終了を選べるようにする。
*/

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

public class JumpGame2 extends JumpGame implements ActionListener {

	private JumpGame game;
	private MenuBar menuBar;
	private MenuItem startItem, quitItem;

	/**コンストラクタ*/
	public JumpGame2() {

		super();

		//メニューバーの生成
		menuBar = new MenuBar();

		//メニューの生成		
		Menu programMenu = new Menu("Program");

		//メニューアイテムの生成
		startItem = new MenuItem("Start");
		quitItem = new MenuItem("Quit");

		// メニューアイテムをメニューに配置
		programMenu.add(startItem);
		programMenu.add(quitItem);

		//メニューをメニューバーに配置
		menuBar.add(programMenu);

		//イベントの登録	
		quitItem.addActionListener(this);
		startItem.addActionListener(this);

	}

	/**メニューのイベントを処理*/
	public void actionPerformed(ActionEvent evt) {

		Object obj = evt.getSource();	//イベントが発生したオブジェクト取得

		if (!gameFlag) {			//GameOverの時だけ処理を行う

			if (obj.equals(startItem)) {

				gameStart();	//再ゲーム
			}
			else if (obj.equals(quitItem)) {
		
				//Canvasを配置しているFrameを取得後
                               	//Frame以下のリソースを解放
				Frame f = (Frame)getParent();
				f.dispose();
				System.exit(0);	//システムの終了
			}
		}
	}

	/**main()*/
	public static void main(String[] args) {

		//メニューを追加
		JumpGame2 sample = new JumpGame2();

		//クローズボタンで終了するように自作したクラス
		MyFrame frame = new MyFrame("JumpGame2");

		frame.setMenuBar(sample.menuBar);		//メニューバーを配置
		frame.add(sample);
		frame.pack();
		frame.setVisible(true);
		sample.gameStart();
	}
}



このプログラムは、前回作成した[JumpGame.java]を拡張したプログラムですので、JumpGame.javaがないと動きません。
JumpGame.javaのgameFragのアクセス制御をprivateではなくpublicにしているのはこのためです。
以下の部分です。

private int meterc;					//メーター減少部分 / 秒
private Image[] im = new Image[MAX_IMAGE];	//キャラのイメージ
private Image box, back, meter;			//障害物と背景、メーターのイメージ

//次の行のみpublicに変更
public boolean gameFlag;				//ゲーム進行フラグ

private int jFlag;					//アニメーション(ジャンプ)の状態
private MediaTracker tracker;			//イメージ通知用
private int key;					//キーコード取得用
private MyTimer timer;				//残り時間設定のためのタイマー
private PlayAudio bgm, se;				//音声の設定



では早速実行してみましょう。


前回作成した[JumpGame.java]を継承し、機能を拡張しています。
前回作成した[MyFrame.java]を利用していますのでクローズボタンを使って終了できます。
前回作成した[MyTimer.java]を利用しています。


時間制限があります。
右から来る障害物を[SPACE]でジャンプして回避します。
[s]キーで再ゲーム開始です。
ただし、ゲームが始まったら一度、マウスで画面のどこかをクリックしなければキーボードの入力を受け付けてくれません。
ハイスコアの更新があります。
メニューから終了を選べます。


JumpGame2.java実行結果
JumpGame2.java実行結果


表示されるフレーム
表示されるフレーム


もうひとつサンプルプログラムを作ってみましょう。


【AwtMenuDraw.java】

/**
*メニューで図形や色などを指定して[Start]で描画
*/

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

public class AwtMenuDraw extends Canvas implements ActionListener {

	private final int OVAL = 0;
	private final int RECT = 1;

	private MenuBar menuBar;
	private MenuItem startItem, quitItem, clearItem;
	private MenuItem drawItem, fillItem;
	private MenuItem ovalItem, rectItem;
	private MenuItem blueItem, redItem;
	private boolean paintFlag;			//塗りつぶさない=false, 塗りつぶす=true
	private boolean clearFlag;
	private int zukeiFlag;			//図形Oval=0,Rect=1
	private Color color;

	/**コンストラクタ*/
	public AwtMenuDraw() {

		setSize(400, 300);
		setBackground(Color.white);

		//メニューバーの生成
		menuBar = new MenuBar();

		//メニューの生成
		Menu programMenu = new Menu("Program");

		//メニューアイテムの生成
		startItem = new MenuItem("Start");
		clearItem = new MenuItem("Clear");
		quitItem = new MenuItem("Quit");

		//メニューアイテムをメニューに配置
		programMenu.add(startItem);
		programMenu.add(clearItem);
		programMenu.addSeparator();	//区切り線を入れる
		programMenu.add(quitItem);

		//メニューの生成
		Menu paintMenu = new Menu("Paint");

		//メニューアイテムの生成
		drawItem = new MenuItem("Draw");
		fillItem = new MenuItem("Fill");

		//メニューアイテムをメニューに配置
		paintMenu.add(drawItem);
		paintMenu.add(fillItem);

		//メニューの生成
		Menu zukeiMenu = new Menu("Zukei");

		//メニューアイテムの生成
		ovalItem = new MenuItem("Oval");
		rectItem = new MenuItem("Rect");

		//メニューアイテムをメニューに配置
		zukeiMenu.add(ovalItem);
		zukeiMenu.add(rectItem);

		//メニューの生成
		Menu colorMenu = new Menu("Color");

		//メニューアイテムの生成
		blueItem = new MenuItem("Blue");
		redItem = new MenuItem("Red");

		//メニューアイテムをメニューに配置
		colorMenu.add(blueItem);
		colorMenu.add(redItem);

		//メニュー(ヘルプメニュー)の生成
		Menu helpMenu = new Menu("Help");

		//メニューアイテムの生成
		MenuItem helpItem = new MenuItem("Help!");

		//メニューアイテムをメニューに配置
		helpMenu.add(helpItem);

		//メニューをメニューバーに配置
		menuBar.add(programMenu);
		menuBar.add(paintMenu);
		menuBar.add(zukeiMenu);
		menuBar.add(colorMenu);
		menuBar.setHelpMenu(helpMenu);

		paintFlag = false;
		clearFlag = false;
		zukeiFlag = 0;
		color = Color.blue;

		//イベントの登録
		startItem.addActionListener(this);
		clearItem.addActionListener(this);
		quitItem.addActionListener(this);
		drawItem.addActionListener(this);
		fillItem.addActionListener(this);
		ovalItem.addActionListener(this);
		rectItem.addActionListener(this);
		blueItem.addActionListener(this);
		redItem.addActionListener(this);
	}

	/**再描写が必要な場合の処理*/
	public void update(Graphics g) {

		int x, y, width, height;

		//clearFlagがtrueなら白でクリア
		if (clearFlag) {

			g.setColor(Color.white);
			g.fillRect(0, 0, getSize().width, getSize().height);
			clearFlag = false;
			return;
		}
		
                //メニューで設定された色
		g.setColor(color);

		//乱数で図形の位置指定
		x = (int)(Math.random()*400);
		y = (int)(Math.random()*300);

		//zukeiFlagによって楕円か矩形かを指定
		//paintFragで塗りつぶしか否かを指定
		width = (int)(Math.random()*200)+10;
		height = (int)(Math.random()*150)+10;

		if (zukeiFlag == OVAL) {

			if (!paintFlag) {

				g.drawArc(x, y, width, height, 0, 360);
			}
			else {

				g.fillArc(x, y, width, height, 0, 360);
			}

		}

		else if (zukeiFlag == RECT) {

			if (!paintFlag) {

				g.drawRect(x, y, width, height);
			}

			else {

				g.fillRect(x, y, width, height);
			}
		}
	}

	/**プログラム起動時と絵の復活時の処理*/
	public void paint(Graphics g) {

		g.setColor(Color.white);
		g.fillRect(0, 0, 400, 300);
	}

	/**メニューのイベントを処理*/
	public void actionPerformed(ActionEvent evt) {

		Object obj = evt.getSource();

		if (obj.equals(startItem)) {
			
			repaint();	//グラフィックス描画
		}

		else if (obj.equals(quitItem)) {

			System.exit(0);	//システム終了
		}

		else if (obj.equals(drawItem)) {
		
			paintFlag = false;
		}

		else if (obj.equals(fillItem)) {

			paintFlag = true;
		}

		else if (obj.equals(ovalItem)) {
	
			zukeiFlag = OVAL;

		}

		else if (obj.equals(rectItem)) {

			zukeiFlag = RECT;
		}

		else if (obj.equals(blueItem)) {

			color = Color.blue;
		}

		else if (obj.equals(redItem)) {

			color = Color.red;
		}

		else if (obj.equals(clearItem)) {

			clearFlag = true;
			repaint();		//グラフィックス描画
		}
	}

	/**main()*/
	public static void main(String[] args) {

		AwtMenuDraw draw = new AwtMenuDraw();
		MyFrame frame = new MyFrame("MenuDraw");

		frame.setMenuBar(draw.menuBar);		//メニューバーを配置
		frame.add(draw);
		frame.pack();
		frame.setVisible(true);
	}
}



java.awt.*と java.event.*をimportしています。
Canvasクラスを継承して、ActionListenerインターフェイスを実装しています。


実行してみましょう。
前回作成した[MyFrame.java]を利用していますのでクローズボタンを使って終了できます。


各メニューから、項目を選択して、startを選択するとランダムな位置に選択した条件の図形が表示されます。
clearを選択すると画面がクリアされます。
Helpは選択しても何も起きません。
Quitを選択すると終了します。








<<前  [TOP]  次>>